drv_eth.c 19.1 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-11-19     SummerGift   first version
S
SummerGift 已提交
9
 * 2018-12-25     zylx         fix some bugs
10
 * 2019-06-10     SummerGift   optimize PHY state detection process 
11 12 13 14 15 16
 */

#include "board.h"
#include "drv_config.h"
#include <netif/ethernetif.h>
#include "lwipopts.h"
S
SummerGift 已提交
17
#include "drv_eth.h"
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

/*
* Emac driver uses CubeMX tool to generate emac and phy's configuration,
* the configuration files can be found in CubeMX_Config floder.
*/

/* debug option */
//#define ETH_RX_DUMP
//#define ETH_TX_DUMP
//#define DRV_DEBUG
#define LOG_TAG             "drv.emac"
#include <drv_log.h>

#define MAX_ADDR_LEN 6

struct rt_stm32_eth
{
    /* inherit from ethernet device */
    struct eth_device parent;

S
SummerGift 已提交
38 39 40 41 42 43
    /* interface address info, hw address */
    rt_uint8_t  dev_addr[MAX_ADDR_LEN];
    /* ETH_Speed */
    uint32_t    ETH_Speed;
    /* ETH_Duplex_Mode */
    uint32_t    ETH_Mode;
44 45 46 47 48 49 50 51 52 53 54
};

static ETH_DMADescTypeDef *DMARxDscrTab, *DMATxDscrTab;
static rt_uint8_t *Rx_Buff, *Tx_Buff;
static  ETH_HandleTypeDef EthHandle;
static struct rt_stm32_eth stm32_eth_device;

#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
{
S
SummerGift 已提交
55
    unsigned char *buf = (unsigned char *)ptr;
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    int i, j;

    for (i = 0; i < buflen; i += 16)
    {
        rt_kprintf("%08X: ", i);

        for (j = 0; j < 16; j++)
            if (i + j < buflen)
                rt_kprintf("%02X ", buf[i + j]);
            else
                rt_kprintf("   ");
        rt_kprintf(" ");

        for (j = 0; j < 16; j++)
            if (i + j < buflen)
                rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
        rt_kprintf("\n");
    }
}
#endif

extern void phy_reset(void);
S
SummerGift 已提交
78
/* EMAC initialization function */
79 80 81 82 83 84
static rt_err_t rt_stm32_eth_init(rt_device_t dev)
{
    __HAL_RCC_ETH_CLK_ENABLE();

    phy_reset();

S
SummerGift 已提交
85
    /* ETHERNET Configuration */
86
    EthHandle.Instance = ETH;
S
SummerGift 已提交
87
    EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
88
    EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
89 90 91 92
    EthHandle.Init.Speed = ETH_SPEED_100M;
    EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
    EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
    EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
93 94
#ifdef RT_LWIP_USING_HW_CHECKSUM
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
S
SummerGift 已提交
95
#else
96
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
97
#endif
S
SummerGift 已提交
98

99 100 101
    HAL_ETH_DeInit(&EthHandle);

    /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
102 103 104 105 106 107 108 109 110 111
    if (HAL_ETH_Init(&EthHandle) != HAL_OK)
    {
        LOG_E("eth hardware init failed");
        return -RT_ERROR;
    }
    else
    {
        LOG_D("eth hardware init success");
    }

112 113 114 115 116 117
    /* Initialize Tx Descriptors list: Chain Mode */
    HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, Tx_Buff, ETH_TXBUFNB);

    /* Initialize Rx Descriptors list: Chain Mode  */
    HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);

S
SummerGift 已提交
118 119 120 121
    /* ETH interrupt Init */
    HAL_NVIC_SetPriority(ETH_IRQn, 0x07, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);

122 123 124 125 126 127 128
    /* Enable MAC and DMA transmission and reception */
    if (HAL_ETH_Start(&EthHandle) == HAL_OK)
    {
        LOG_D("emac hardware start");
    }
    else
    {
S
SummerGift 已提交
129 130
        LOG_E("emac hardware start faild");
        return -RT_ERROR;
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    }

    return RT_EOK;
}

static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
{
    LOG_D("emac open");
    return RT_EOK;
}

static rt_err_t rt_stm32_eth_close(rt_device_t dev)
{
    LOG_D("emac close");
    return RT_EOK;
}

S
SummerGift 已提交
148
static rt_size_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
149 150 151 152 153 154
{
    LOG_D("emac read");
    rt_set_errno(-RT_ENOSYS);
    return 0;
}

S
SummerGift 已提交
155
static rt_size_t rt_stm32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
156 157 158 159 160 161 162 163
{
    LOG_D("emac write");
    rt_set_errno(-RT_ENOSYS);
    return 0;
}

static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
{
S
SummerGift 已提交
164
    switch (cmd)
165 166 167
    {
    case NIOCTL_GADDR:
        /* get mac address */
S
SummerGift 已提交
168
        if (args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
169 170 171 172 173 174 175 176 177 178 179 180
        else return -RT_ERROR;
        break;

    default :
        break;
    }

    return RT_EOK;
}

/* ethernet device interface */
/* transmit data*/
S
SummerGift 已提交
181
rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
{
    rt_err_t ret = RT_ERROR;
    HAL_StatusTypeDef state;
    struct pbuf *q;
    uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
    __IO ETH_DMADescTypeDef *DmaTxDesc;
    uint32_t framelength = 0;
    uint32_t bufferoffset = 0;
    uint32_t byteslefttocopy = 0;
    uint32_t payloadoffset = 0;

    DmaTxDesc = EthHandle.TxDesc;
    bufferoffset = 0;

    /* copy frame from pbufs to driver buffers */
S
SummerGift 已提交
197
    for (q = p; q != NULL; q = q->next)
198 199
    {
        /* Is this buffer available? If not, goto error */
S
SummerGift 已提交
200
        if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
201
        {
202
            LOG_D("buffer not valid");
203 204 205 206 207 208 209 210 211
            ret = ERR_USE;
            goto error;
        }

        /* Get bytes in current lwIP buffer */
        byteslefttocopy = q->len;
        payloadoffset = 0;

        /* Check if the length of data to copy is bigger than Tx buffer size*/
S
SummerGift 已提交
212
        while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
213 214
        {
            /* Copy data to Tx buffer*/
S
SummerGift 已提交
215
            memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
216 217 218 219 220

            /* Point to next descriptor */
            DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);

            /* Check if the buffer is available */
S
SummerGift 已提交
221
            if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
222
            {
S
SummerGift 已提交
223
                LOG_E("dma tx desc buffer is not valid");
224 225 226 227 228 229 230 231 232 233 234 235 236
                ret = ERR_USE;
                goto error;
            }

            buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);

            byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
            payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
            framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
            bufferoffset = 0;
        }

        /* Copy the remaining bytes */
S
SummerGift 已提交
237
        memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
238 239 240 241 242 243 244 245 246 247 248 249
        bufferoffset = bufferoffset + byteslefttocopy;
        framelength = framelength + byteslefttocopy;
    }

#ifdef ETH_TX_DUMP
    dump_hex(buffer, p->tot_len);
#endif

    /* Prepare transmit descriptors to give to DMA */
    /* TODO Optimize data send speed*/
    LOG_D("transmit frame lenth :%d", framelength);

S
SummerGift 已提交
250 251 252
    /* wait for unlocked */
    while (EthHandle.Lock == HAL_LOCKED);

253 254 255
    state = HAL_ETH_TransmitFrame(&EthHandle, framelength);
    if (state != HAL_OK)
    {
S
SummerGift 已提交
256
        LOG_E("eth transmit frame faild: %d", state);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    }

    ret = ERR_OK;

error:

    /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
    if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
    {
        /* Clear TUS ETHERNET DMA flag */
        EthHandle.Instance->DMASR = ETH_DMASR_TUS;

        /* Resume DMA transmission*/
        EthHandle.Instance->DMATPDR = 0;
    }

    return ret;
}

/* receive data*/
struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
{

    struct pbuf *p = NULL;
    struct pbuf *q = NULL;
    HAL_StatusTypeDef state;
    uint16_t len = 0;
    uint8_t *buffer;
    __IO ETH_DMADescTypeDef *dmarxdesc;
    uint32_t bufferoffset = 0;
    uint32_t payloadoffset = 0;
    uint32_t byteslefttocopy = 0;
    uint32_t i = 0;

    /* Get received frame */
    state = HAL_ETH_GetReceivedFrame_IT(&EthHandle);
    if (state != HAL_OK)
    {
        LOG_D("receive frame faild");
        return NULL;
    }

    /* Obtain the size of the packet and put it into the "len" variable. */
    len = EthHandle.RxFrameInfos.length;
    buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;

    LOG_D("receive frame len : %d", len);

    if (len > 0)
    {
        /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
        p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
    }

#ifdef ETH_RX_DUMP
    dump_hex(buffer, p->tot_len);
#endif

    if (p != NULL)
    {
        dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
        bufferoffset = 0;
S
SummerGift 已提交
319
        for (q = p; q != NULL; q = q->next)
320 321 322 323 324
        {
            byteslefttocopy = q->len;
            payloadoffset = 0;

            /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
S
SummerGift 已提交
325
            while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE)
326 327
            {
                /* Copy data to pbuf */
S
SummerGift 已提交
328
                memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
329 330 331 332 333 334 335 336 337 338

                /* Point to next descriptor */
                dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
                buffer = (uint8_t *)(dmarxdesc->Buffer1Addr);

                byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
                payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
                bufferoffset = 0;
            }
            /* Copy remaining data in pbuf */
S
SummerGift 已提交
339
            memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
            bufferoffset = bufferoffset + byteslefttocopy;
        }
    }

    /* Release descriptors to DMA */
    /* Point to first descriptor */
    dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
    /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
    for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++)
    {
        dmarxdesc->Status |= ETH_DMARXDESC_OWN;
        dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
    }

    /* Clear Segment_Count */
    EthHandle.RxFrameInfos.SegCount = 0;

    /* When Rx Buffer unavailable flag is set: clear it and resume reception */
    if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)
    {
        /* Clear RBUS ETHERNET DMA flag */
        EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
        /* Resume DMA reception */
        EthHandle.Instance->DMARPDR = 0;
    }

    return p;
}

/* interrupt service routine */
void ETH_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    HAL_ETH_IRQHandler(&EthHandle);

    /* leave interrupt */
    rt_interrupt_leave();
}

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
    rt_err_t result;
    result = eth_device_ready(&(stm32_eth_device.parent));
S
SummerGift 已提交
385 386
    if (result != RT_EOK)
        LOG_E("RX err = %d", result);
387 388 389 390
}

void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
{
S
SummerGift 已提交
391
    LOG_E("eth err");
392 393
}

S
SummerGift 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
#ifdef PHY_USING_INTERRUPT_MODE
static void eth_phy_isr(void *args)
{
    rt_uint32_t status = 0;
    static rt_uint8_t link_status = 1;

    HAL_ETH_ReadPHYRegister(&EthHandle, PHY_INTERRUPT_FLAG_REG, (uint32_t *)&status);
    LOG_D("phy interrupt status reg is 0x%X", status);
    HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
    LOG_D("phy basic status reg is 0x%X", status);

    if (status & PHY_LINKED_STATUS_MASK)
    {
        if (link_status == 0)
        {
            link_status = 1;
            LOG_D("link up");
            /* send link up. */
            eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
        }
    }
    else
    {
        if (link_status == 1)
        {
            link_status = 0;
            LOG_I("link down");
            /* send link down. */
            eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
        }
    }
}
#endif /* PHY_USING_INTERRUPT_MODE */

428 429 430 431 432 433
static uint8_t phy_speed = 0;
#define PHY_LINK_MASK       (1<<0)
static void phy_monitor_thread_entry(void *parameter)
{
    uint8_t phy_addr = 0xFF;
    uint8_t phy_speed_new = 0;
S
SummerGift 已提交
434
    rt_uint32_t status = 0;
S
SummerGift 已提交
435
    uint8_t detected_count = 0;
436

S
SummerGift 已提交
437
    while(phy_addr == 0xFF)
438
    {
S
SummerGift 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451
        /* phy search */
        rt_uint32_t i, temp;
        for (i = 0; i <= 0x1F; i++)
        {
            EthHandle.Init.PhyAddress = i;
            HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);

            if (temp != 0xFFFF && temp != 0x00)
            {
                phy_addr = i;
                break;
            }
        }
452

S
SummerGift 已提交
453 454
        detected_count++;
        rt_thread_mdelay(1000);
S
SummerGift 已提交
455

S
SummerGift 已提交
456
        if (detected_count > 10)
457
        {
S
SummerGift 已提交
458
            LOG_E("No PHY device was detected, please check hardware!");
459 460 461
        }
    }

S
SummerGift 已提交
462
    LOG_D("Found a phy, address:0x%02X", phy_addr);
463 464 465

    /* RESET PHY */
    LOG_D("RESET PHY!");
S
SummerGift 已提交
466 467 468
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
    rt_thread_mdelay(2000);
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
469

S
SummerGift 已提交
470
    while (1)
471 472 473
    {
        phy_speed_new = 0;

474
        if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status) == HAL_OK)
475
        {
476 477 478
            LOG_D("PHY BASIC STATUS REG:0x%04X", status);
            
            if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
479
            {
480
                rt_uint32_t SR;
481

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
                phy_speed_new = PHY_LINK_MASK;

                if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_Status_REG, (uint32_t *)&SR) == HAL_OK)
                {
                    LOG_D("PHY Control/Status REG:0x%04X ", SR); 

                    if (SR & PHY_100M_MASK)
                    {
                        phy_speed_new |= PHY_100M_MASK;
                    }
                    else if (SR & PHY_10M_MASK)
                    {
                        phy_speed_new |= PHY_10M_MASK;
                    }

                    if (SR & PHY_FULL_DUPLEX_MASK)
                    {
                        phy_speed_new |= PHY_FULL_DUPLEX_MASK;
                    }
                }
                else
                {
                    LOG_D("PHY Control/Status REG read error."); 
S
SummerGift 已提交
505
                    continue;
506
                }
507 508
            }
        }
S
SummerGift 已提交
509 510 511 512
        else
        {
            continue;
        }
513 514

        /* linkchange */
S
SummerGift 已提交
515
        if (phy_speed_new != phy_speed)
516
        {
S
SummerGift 已提交
517
            if (phy_speed_new & PHY_LINK_MASK)
518 519 520
            {
                LOG_D("link up ");

S
SummerGift 已提交
521
                if (phy_speed_new & PHY_100M_MASK)
522 523 524 525 526 527 528 529 530 531
                {
                    LOG_D("100Mbps");
                    stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
                }
                else
                {
                    stm32_eth_device.ETH_Speed = ETH_SPEED_10M;
                    LOG_D("10Mbps");
                }

S
SummerGift 已提交
532
                if (phy_speed_new & PHY_FULL_DUPLEX_MASK)
533 534 535 536 537 538 539 540 541 542
                {
                    LOG_D("full-duplex");
                    stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
                }
                else
                {
                    LOG_D("half-duplex");
                    stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
                }

543 544 545
                /* send link up. */
                eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);

S
SummerGift 已提交
546 547 548 549 550 551 552 553 554 555 556
#ifdef PHY_USING_INTERRUPT_MODE
                /* configuration intterrupt pin */
                rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
                rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
                rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);

                /* enable phy interrupt */
                HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MSAK_REG, PHY_INT_MASK);

                break;
#endif
557 558 559
            } /* link up. */
            else
            {
S
SummerGift 已提交
560
                LOG_I("link down");
561 562
                /* send link down. */
                eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
S
SummerGift 已提交
563
            }
564
            phy_speed = phy_speed_new;
S
SummerGift 已提交
565
        }
566 567

        rt_thread_delay(RT_TICK_PER_SECOND);
S
SummerGift 已提交
568
    }
569 570 571 572 573
}

/* Register the EMAC device */
static int rt_hw_stm32_eth_init(void)
{
S
SummerGift 已提交
574 575
    rt_err_t state = RT_EOK;

576 577 578 579 580
    /* Prepare receive and send buffers */
    Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RXBUFNB, ETH_MAX_PACKET_SIZE);
    if (Rx_Buff == RT_NULL)
    {
        LOG_E("No memory");
S
SummerGift 已提交
581
        state = -RT_ENOMEM;
S
SummerGift 已提交
582
        goto __exit;
583
    }
S
SummerGift 已提交
584

585 586 587 588
    Tx_Buff = (rt_uint8_t *)rt_calloc(ETH_TXBUFNB, ETH_MAX_PACKET_SIZE);
    if (Rx_Buff == RT_NULL)
    {
        LOG_E("No memory");
S
SummerGift 已提交
589
        state = -RT_ENOMEM;
S
SummerGift 已提交
590
        goto __exit;
591
    }
S
SummerGift 已提交
592 593

    DMARxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_RXBUFNB, sizeof(ETH_DMADescTypeDef));
594 595 596
    if (DMARxDscrTab == RT_NULL)
    {
        LOG_E("No memory");
S
SummerGift 已提交
597
        state = -RT_ENOMEM;
S
SummerGift 已提交
598
        goto __exit;
599
    }
S
SummerGift 已提交
600 601

    DMATxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_TXBUFNB, sizeof(ETH_DMADescTypeDef));
602 603 604
    if (DMATxDscrTab == RT_NULL)
    {
        LOG_E("No memory");
S
SummerGift 已提交
605
        state = -RT_ENOMEM;
S
SummerGift 已提交
606
        goto __exit;
607 608 609 610 611 612 613 614 615 616
    }

    stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
    stm32_eth_device.ETH_Mode  = ETH_MODE_FULLDUPLEX;

    /* OUI 00-80-E1 STMICROELECTRONICS. */
    stm32_eth_device.dev_addr[0] = 0x00;
    stm32_eth_device.dev_addr[1] = 0x80;
    stm32_eth_device.dev_addr[2] = 0xE1;
    /* generate MAC addr from 96bit unique ID (only for test). */
S
SummerGift 已提交
617 618 619
    stm32_eth_device.dev_addr[3] = *(rt_uint8_t *)(UID_BASE + 4);
    stm32_eth_device.dev_addr[4] = *(rt_uint8_t *)(UID_BASE + 2);
    stm32_eth_device.dev_addr[5] = *(rt_uint8_t *)(UID_BASE + 0);
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

    stm32_eth_device.parent.parent.init       = rt_stm32_eth_init;
    stm32_eth_device.parent.parent.open       = rt_stm32_eth_open;
    stm32_eth_device.parent.parent.close      = rt_stm32_eth_close;
    stm32_eth_device.parent.parent.read       = rt_stm32_eth_read;
    stm32_eth_device.parent.parent.write      = rt_stm32_eth_write;
    stm32_eth_device.parent.parent.control    = rt_stm32_eth_control;
    stm32_eth_device.parent.parent.user_data  = RT_NULL;

    stm32_eth_device.parent.eth_rx     = rt_stm32_eth_rx;
    stm32_eth_device.parent.eth_tx     = rt_stm32_eth_tx;

    /* register eth device */
    state = eth_device_init(&(stm32_eth_device.parent), "e0");
    if (RT_EOK == state)
    {
        LOG_D("emac device init success");
    }
    else
    {
S
SummerGift 已提交
640
        LOG_E("emac device init faild: %d", state);
S
SummerGift 已提交
641 642
        state = -RT_ERROR;
        goto __exit;
643
    }
S
SummerGift 已提交
644

645 646 647 648 649 650 651 652 653 654
    /* start phy monitor */
    rt_thread_t tid;
    tid = rt_thread_create("phy",
                           phy_monitor_thread_entry,
                           RT_NULL,
                           1024,
                           RT_THREAD_PRIORITY_MAX - 2,
                           2);
    if (tid != RT_NULL)
    {
S
SummerGift 已提交
655
        rt_thread_startup(tid);
656
    }
S
SummerGift 已提交
657 658 659 660
    else
    {
        state = -RT_ERROR;
    }
S
SummerGift 已提交
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
__exit:
    if (state != RT_EOK)
    {
        if (Rx_Buff)
        {
            rt_free(Rx_Buff);
        }

        if (Tx_Buff)
        {
            rt_free(Tx_Buff);
        }

        if (DMARxDscrTab)
        {
            rt_free(DMARxDscrTab);
        }

        if (DMATxDscrTab)
        {
            rt_free(DMATxDscrTab);
        }
    }

685 686
    return state;
}
687
INIT_DEVICE_EXPORT(rt_hw_stm32_eth_init);