[AT32F407] LAN8720A 不能获取IP,求RT-Thread的驱动

[复制链接]
2623|3
 楼主| dongly 发表于 2022-6-18 09:45 | 显示全部楼层 |阅读模式
本帖最后由 dongly 于 2022-6-18 11:31 编辑

  • 问题: 在rt-thread 最新版下,加入LAN8720A的支持,不能获取IP,但2个网络指示灯亮,debug时,有收发数据
  • 硬件: AT32F407VGT7 + LAN7820A,RMII_RX[0..1]为PC4,PC5,LAN8720A 自带25MHz晶振
  • 用雅特力的例程可以工作,说明硬件没问题
  • 求指导,或移植好的驱动
  • drv_emac.h
    1. /*
    2. * Copyright (c) 2006-2021, RT-Thread Development Team
    3. *
    4. * SPDX-License-Identifier: Apache-2.0
    5. *
    6. * Change Logs:
    7. * Date           Author       Notes
    8. * 2022-05-16     shelton      first version
    9. */

    10. #ifndef __DRV_EMAC_H__
    11. #define __DRV_EMAC_H__

    12. #include "drv_common.h"
    13. #include <rtdevice.h>
    14. #include <rthw.h>
    15. #include <rtthread.h>

    16. /* the phy basic control register */
    17. #define PHY_BASIC_CONTROL_REG     0x00U
    18. #define PHY_RESET_MASK            (1 << 15)
    19. #define PHY_AUTO_NEGOTIATION_MASK (1 << 12)

    20. /* the phy basic status register */
    21. #define PHY_BASIC_STATUS_REG       0x01U
    22. #define PHY_LINKED_STATUS_MASK     (1 << 2)
    23. #define PHY_AUTONEGO_COMPLETE_MASK (1 << 5)

    24. /* the phy id one register */
    25. #define PHY_ID1_REG 0x02U
    26. /* the phy id two register */
    27. #define PHY_ID2_REG 0x03U
    28. /* the phy auto-negotiate advertise register */
    29. #define PHY_AUTONEG_ADVERTISE_REG 0x04U

    30. #if defined(PHY_USING_DM9162)
    31. #define PHY_CONTROL_REG      (0x00) /*!< basic mode control register */
    32. #define PHY_STATUS_REG       (0x01) /*!< basic mode status register */
    33. #define PHY_SPECIFIED_CS_REG (0x11) /*!< specified configuration and status register */
    34. /* phy control register */
    35. #define PHY_AUTO_NEGOTIATION_BIT (0x1000) /*!< enable auto negotiation */
    36. #define PHY_LOOPBACK_BIT         (0x4000) /*!< enable loopback */
    37. #define PHY_RESET_BIT            (0x8000) /*!< reset phy */
    38. /* phy status register */
    39. #define PHY_LINKED_STATUS_BIT (0x0004) /*!< link status */
    40. #define PHY_NEGO_COMPLETE_BIT (0x0020) /*!< auto negotiation complete */
    41. /* phy specified control/status register */
    42. #define PHY_FULL_DUPLEX_100MBPS_BIT (0x8000) /*!< full duplex 100 mbps */
    43. #define PHY_HALF_DUPLEX_100MBPS_BIT (0x4000) /*!< half duplex 100 mbps */
    44. #define PHY_FULL_DUPLEX_10MBPS_BIT  (0x2000) /*!< full duplex 10 mbps */
    45. #define PHY_HALF_DUPLEX_10MBPS_BIT  (0x1000) /*!< half duplex 10 mbps */
    46. #define PHY_DUPLEX_MODE                                                                            \
    47.     (PHY_FULL_DUPLEX_100MBPS_BIT | PHY_FULL_DUPLEX_10MBPS_BIT) /*!< full duplex mode */
    48. #define PHY_SPEED_MODE (PHY_FULL_DUPLEX_10MBPS_BIT | PHY_HALF_DUPLEX_10MBPS_BIT) /*!< 10 mbps */
    49. /*  the phy interrupt source flag register. */
    50. #define PHY_INTERRUPT_FLAG_REG 0x15U
    51. /*  the phy interrupt mask register. */
    52. #define PHY_INTERRUPT_MASK_REG 0x15U
    53. #define PHY_LINK_CHANGE_FLAG   (1 << 2)
    54. #define PHY_LINK_CHANGE_MASK   (1 << 9)
    55. #define PHY_INT_MASK           0
    56. #elif defined(PHY_USING_DP83848)
    57. #define PHY_CONTROL_REG          (0x00)   /*!< basic mode control register */
    58. #define PHY_STATUS_REG           (0x01)   /*!< basic mode status register */
    59. #define PHY_SPECIFIED_CS_REG     (0x10)   /*!< phy status register */
    60. /* phy control register */
    61. #define PHY_AUTO_NEGOTIATION_BIT (0x1000) /*!< enable auto negotiation */
    62. #define PHY_LOOPBACK_BIT         (0x4000) /*!< enable loopback */
    63. #define PHY_RESET_BIT            (0x8000) /*!< reset phy */
    64. /* phy status register */
    65. #define PHY_LINKED_STATUS_BIT    (0x0004) /*!< link status */
    66. #define PHY_NEGO_COMPLETE_BIT    (0x0020) /*!< auto negotiation complete */

    67. #define PHY_DUPLEX_MODE        (0x0004) /*!< full duplex mode */
    68. #define PHY_SPEED_MODE         (0x0002) /*!< 10 mbps */

    69. /*  the phy interrupt source flag register. */
    70. #define PHY_INTERRUPT_FLAG_REG 0x12U
    71. #define PHY_LINK_CHANGE_FLAG   (1 << 13)
    72. /*  the phy interrupt control register. */
    73. #define PHY_INTERRUPT_CTRL_REG 0x11U
    74. #define PHY_INTERRUPT_EN       ((1 << 0) | (1 << 1))
    75. /*  the phy interrupt mask register. */
    76. #define PHY_INTERRUPT_MASK_REG 0x12U
    77. #define PHY_INT_MASK           (1 << 5)
    78. #elif defined(PHY_USING_LAN8720A)
    79. #define PHY_CONTROL_REG      (0x00) /*!< basic mode control register */
    80. #define PHY_STATUS_REG       (0x01) /*!< basic mode status register */
    81. #define PHY_SPECIFIED_CS_REG (0x1F) /*!< phy status register */
    82. /* phy control register */
    83. #define PHY_AUTO_NEGOTIATION_BIT (0x1000) /*!< enable auto negotiation */
    84. #define PHY_LOOPBACK_BIT         (0x4000) /*!< enable loopback */
    85. #define PHY_RESET_BIT            (0x8000) /*!< reset phy */
    86. /* phy status register */
    87. #define PHY_LINKED_STATUS_BIT    (0x0004) /*!< link status */
    88. #define PHY_NEGO_COMPLETE_BIT    (0x0020) /*!< auto negotiation complete */

    89. #define PHY_DUPLEX_MODE (0x0100) /*!< full duplex mode */
    90. #define PHY_SPEED_MODE  (0x2000) /*!< 100 mbps */

    91. #define PHY_FULL_DUPLEX_100MBPS_BIT (0x0018) /*!< full duplex 100 mbps */
    92. #define PHY_HALF_DUPLEX_100MBPS_BIT (0x0008) /*!< half duplex 100 mbps */
    93. #define PHY_FULL_DUPLEX_10MBPS_BIT  (0x0014) /*!< full duplex 10 mbps */
    94. #define PHY_HALF_DUPLEX_10MBPS_BIT  (0x0004) /*!< half duplex 10 mbps */
    95. #define PHY_DUPLEX_MBPS_MSK         (0x001C)
    96. /*  The PHY interrupt source flag register. */
    97. #define PHY_INTERRUPT_FLAG_REG      (0x01DU)
    98. #endif

    99. #endif /* __DRV_EMAC_H__ */

    1. /*
    2. * Copyright (c) 2006-2021, RT-Thread Development Team
    3. *
    4. * SPDX-License-Identifier: Apache-2.0
    5. *
    6. * Change Logs:
    7. * Date           Author       Notes
    8. * 2022-05-16     shelton      first version
    9. */

    10. #include "drv_emac.h"
    11. #include <netif/ethernetif.h>
    12. #include <lwipopts.h>

    13. /* debug option */
    14. // #define EMAC_RX_DUMP
    15. // #define EMAC_TX_DUMP
    16. #define DRV_DEBUG
    17. #define LOG_TAG                         "drv.emac"
    18. #include <drv_log.h>

    19. /* emac memory buffer configuration */
    20. #define EMAC_NUM_RX_BUF                 4    /* 0x1800 for rx (4 * 1536 = 6k)      */
    21. #define EMAC_NUM_TX_BUF                 2    /* 0x0600 for tx (2 * 1536 = 3k)      */

    22. #define MAX_ADDR_LEN                    6

    23. struct rt_at32_emac
    24. {
    25.     /* inherit from ethernet device */
    26.     struct eth_device parent;
    27. #ifndef PHY_USING_INTERRUPT_MODE
    28.     rt_timer_t poll_link_timer;
    29. #endif

    30.     /* interface address info, hw address */
    31.     rt_uint8_t dev_addr[MAX_ADDR_LEN];
    32.     /* emac_speed */
    33.     emac_speed_type emac_speed;
    34.     /* emac_duplex_mode */
    35.     emac_duplex_type emac_mode;
    36. };

    37. static emac_dma_desc_type *dma_rx_dscr_tab, *dma_tx_dscr_tab;
    38. extern emac_dma_desc_type *dma_rx_desc_to_get, *dma_tx_desc_to_set;

    39. static rt_uint8_t *rx_buff, *tx_buff;
    40. static struct rt_at32_emac at32_emac_device;
    41. static uint8_t phy_addr = 0xFF;
    42. static struct rt_semaphore tx_wait;
    43. static rt_bool_t tx_is_waiting = RT_FALSE;

    44. #if defined(EMAC_RX_DUMP) || defined(EMAC_TX_DUMP)
    45. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
    46. static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
    47. {
    48.     unsigned char *buf = (unsigned char *)ptr;
    49.     int i, j;

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

    53.         for (j = 0; j < 16; j++)
    54.             if (i + j < buflen)
    55.                 rt_kprintf("%02X ", buf[i + j]);
    56.             else
    57.                 rt_kprintf("   ");
    58.         rt_kprintf(" ");

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

    66. // /**
    67. //   * [url=home.php?mod=space&uid=247401]@brief[/url] phy reset
    68. //   */
    69. // static void phy_reset(void)
    70. // {
    71. //     gpio_init_type gpio_init_struct;

    72. // #if defined (SOC_SERIES_AT32F437)
    73. //     crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
    74. //     crm_periph_clock_enable(CRM_GPIOG_PERIPH_CLOCK, TRUE);

    75. //     gpio_default_para_init(&gpio_init_struct);
    76. //     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    77. //     gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    78. //     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    79. //     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    80. //     gpio_init_struct.gpio_pins = GPIO_PINS_15;
    81. //     gpio_init(GPIOE, &gpio_init_struct);

    82. //     gpio_init_struct.gpio_pins = GPIO_PINS_15;
    83. //     gpio_init(GPIOG, &gpio_init_struct);

    84. //     gpio_bits_reset(GPIOE, GPIO_PINS_15);
    85. //     gpio_bits_reset(GPIOG, GPIO_PINS_15);
    86. //     rt_thread_mdelay(2);
    87. //     gpio_bits_set(GPIOE, GPIO_PINS_15);
    88. // #endif
    89. // #if defined (SOC_SERIES_AT32F407)
    90. //     crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

    91. //     gpio_default_para_init(&gpio_init_struct);
    92. //     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    93. //     gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    94. //     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    95. //     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    96. //     gpio_init_struct.gpio_pins = GPIO_PINS_8;
    97. //     gpio_init(GPIOC, &gpio_init_struct);

    98. //     gpio_bits_reset(GPIOC, GPIO_PINS_8);
    99. //     rt_thread_mdelay(2);
    100. //     gpio_bits_set(GPIOC, GPIO_PINS_8);
    101. // #endif
    102. //     rt_thread_mdelay(2000);
    103. // }


    104. /**
    105.   * [url=home.php?mod=space&uid=247401]@brief[/url] reset phy register
    106.   */
    107. static error_status emac_phy_register_reset(void)
    108. {
    109.     uint16_t data = 0;
    110.     uint32_t timeout = 0;
    111.     uint32_t i = 0;

    112.     if(emac_phy_register_write(phy_addr, PHY_CONTROL_REG, PHY_RESET_BIT) == ERROR)
    113.     {
    114.         return ERROR;
    115.     }

    116.     for(i = 0; i < 0x000FFFFF; i++);

    117.     do
    118.     {
    119.         timeout++;
    120.         if(emac_phy_register_read(phy_addr, PHY_CONTROL_REG, &data) == ERROR)
    121.         {
    122.             return ERROR;
    123.         }
    124.     } while((data & PHY_RESET_BIT) && (timeout < PHY_TIMEOUT));

    125.     for(i = 0; i < 0x00FFFFF; i++);
    126.     if(timeout == PHY_TIMEOUT)
    127.     {
    128.         return ERROR;
    129.     }
    130.     return SUCCESS;
    131. }

    132. /**
    133.   * [url=home.php?mod=space&uid=247401]@brief[/url] set mac speed related parameters
    134.   */
    135. static error_status emac_speed_config(emac_auto_negotiation_type nego, emac_duplex_type mode, emac_speed_type speed)
    136. {
    137.     uint16_t data = 0;
    138.     uint32_t timeout = 0;
    139.     if(nego == EMAC_AUTO_NEGOTIATION_ON)
    140.     {
    141.         do
    142.         {
    143.             timeout++;
    144.             if(emac_phy_register_read(phy_addr, PHY_STATUS_REG, &data) == ERROR)
    145.             {
    146.               return ERROR;
    147.             }
    148.         } while(!(data & PHY_LINKED_STATUS_BIT) && (timeout < PHY_TIMEOUT));

    149.         if(timeout == PHY_TIMEOUT)
    150.         {
    151.             return ERROR;
    152.         }

    153.         timeout = 0;

    154.         if(emac_phy_register_write(phy_addr, PHY_CONTROL_REG, PHY_AUTO_NEGOTIATION_BIT) == ERROR)
    155.         {
    156.             return ERROR;
    157.         }

    158.         do
    159.         {
    160.             timeout++;
    161.             if(emac_phy_register_read(phy_addr, PHY_STATUS_REG, &data) == ERROR)
    162.             {
    163.                 return ERROR;
    164.             }
    165.         } while(!(data & PHY_NEGO_COMPLETE_BIT) && (timeout < PHY_TIMEOUT));

    166.         if(timeout == PHY_TIMEOUT)
    167.         {
    168.             return ERROR;
    169.         }

    170.         if(emac_phy_register_read(phy_addr, PHY_SPECIFIED_CS_REG, &data) == ERROR)
    171.         {
    172.             return ERROR;
    173.         }
    174. #ifdef PHY_USING_DM9162
    175.         if(data & PHY_FULL_DUPLEX_100MBPS_BIT)
    176.         {
    177.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    178.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    179.         }
    180.         else if(data & PHY_HALF_DUPLEX_100MBPS_BIT)
    181.         {
    182.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    183.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    184.         }
    185.         else if(data & PHY_FULL_DUPLEX_10MBPS_BIT)
    186.         {
    187.             emac_fast_speed_set(EMAC_SPEED_10MBPS);
    188.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    189.         }
    190.         else if(data & PHY_HALF_DUPLEX_10MBPS_BIT)
    191.         {
    192.             emac_fast_speed_set(EMAC_SPEED_10MBPS);
    193.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    194.         }
    195. #endif
    196. #ifdef PHY_USING_DP83848
    197.         if(data & PHY_DUPLEX_MODE)
    198.         {
    199.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    200.         }
    201.         else
    202.         {
    203.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    204.         }
    205.         if(data & PHY_SPEED_MODE)
    206.         {
    207.             emac_fast_speed_set(EMAC_SPEED_10MBPS);
    208.         }
    209.         else
    210.         {
    211.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    212.         }
    213. #endif
    214. #ifdef PHY_USING_LAN8720A
    215.         if ((data & PHY_DUPLEX_MBPS_MSK) == PHY_FULL_DUPLEX_100MBPS_BIT)
    216.         {
    217.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    218.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    219.         }

    220.         if ((data & PHY_DUPLEX_MBPS_MSK) == PHY_HALF_DUPLEX_100MBPS_BIT)
    221.         {
    222.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    223.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    224.         }

    225.         if ((data & PHY_DUPLEX_MBPS_MSK) == PHY_FULL_DUPLEX_10MBPS_BIT)
    226.         {
    227.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    228.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    229.         }

    230.         if ((data & PHY_DUPLEX_MBPS_MSK) == PHY_FULL_DUPLEX_10MBPS_BIT)
    231.         {
    232.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    233.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    234.         }
    235. #endif
    236.     }
    237.     else
    238.     {
    239.         if(emac_phy_register_write(phy_addr, PHY_CONTROL_REG, (uint16_t)((mode << 8) | (speed << 13))) == ERROR)
    240.         {
    241.             return ERROR;
    242.         }
    243.         if(speed == EMAC_SPEED_100MBPS)
    244.         {
    245.             emac_fast_speed_set(EMAC_SPEED_100MBPS);
    246.         }
    247.         else
    248.         {
    249.             emac_fast_speed_set(EMAC_SPEED_10MBPS);
    250.         }
    251.         if(mode == EMAC_FULL_DUPLEX)
    252.         {
    253.             emac_duplex_mode_set(EMAC_FULL_DUPLEX);
    254.         }
    255.         else
    256.         {
    257.             emac_duplex_mode_set(EMAC_HALF_DUPLEX);
    258.         }
    259.     }

    260.     return SUCCESS;
    261. }

    262. /**
    263.   * [url=home.php?mod=space&uid=247401]@brief[/url] initialize emac phy
    264.   */
    265. static error_status emac_phy_init(emac_control_config_type *control_para)
    266. {
    267.     emac_clock_range_set();
    268.     if(emac_phy_register_reset() == ERROR)
    269.     {
    270.         return ERROR;
    271.     }
    272.     if(emac_speed_config(control_para->auto_nego, control_para->duplex_mode, control_para->fast_ethernet_speed) == ERROR)
    273.     {
    274.         return ERROR;
    275.     }

    276.     emac_control_config(control_para);
    277.     return SUCCESS;
    278. }

    279. /**
    280.   * [url=home.php?mod=space&uid=247401]@brief[/url] emac initialization function
    281.   */
    282. static rt_err_t rt_at32_emac_init(rt_device_t dev)
    283. {
    284.     emac_control_config_type mac_control_para;
    285.     emac_dma_config_type dma_control_para;

    286.     /* check till phy detected */
    287.     while(phy_addr == 0xFF)
    288.     {
    289.         rt_thread_mdelay(1000);
    290.     }

    291.     /* emac reset */
    292.     emac_reset();

    293.     /* software reset emac dma */
    294.     emac_dma_software_reset_set();
    295.     while(emac_dma_software_reset_get() == SET);

    296.     emac_control_para_init(&mac_control_para);
    297.     mac_control_para.auto_nego = EMAC_AUTO_NEGOTIATION_ON;
    298.     if(emac_phy_init(&mac_control_para) == ERROR)
    299.     {
    300.         LOG_E("emac hardware init failed");
    301.         return -RT_ERROR;
    302.     }
    303.     else
    304.     {
    305.         LOG_D("emac hardware init success");
    306.     }

    307.     emac_transmit_flow_control_enable(TRUE);
    308.     emac_zero_quanta_pause_disable(TRUE);

    309.     /* set mac address */
    310.     emac_local_address_set(at32_emac_device.dev_addr);

    311.     /* set emac dma rx link list */
    312.     emac_dma_descriptor_list_address_set(EMAC_DMA_RECEIVE, dma_rx_dscr_tab, rx_buff, EMAC_NUM_RX_BUF);
    313.     /* set emac dma tx link list */
    314.     emac_dma_descriptor_list_address_set(EMAC_DMA_TRANSMIT, dma_tx_dscr_tab, tx_buff, EMAC_NUM_TX_BUF);

    315.     /* emac interrupt init */
    316.     emac_dma_config(&dma_control_para);
    317.     emac_dma_interrupt_enable(EMAC_DMA_INTERRUPT_NORMAL_SUMMARY, TRUE);
    318.     emac_dma_interrupt_enable(EMAC_DMA_INTERRUPT_RX, TRUE);
    319.     nvic_irq_enable(EMAC_IRQn, 0x07, 0);

    320.     /* enable emac */
    321.     emac_start();

    322.     return RT_EOK;
    323. }

    324. static rt_err_t rt_at32_emac_open(rt_device_t dev, rt_uint16_t oflag)
    325. {
    326.     LOG_D("emac open");
    327.     return RT_EOK;
    328. }

    329. static rt_err_t rt_at32_emac_close(rt_device_t dev)
    330. {
    331.     LOG_D("emac close");
    332.     return RT_EOK;
    333. }

    334. static rt_size_t rt_at32_emac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
    335. {
    336.     LOG_D("emac read");
    337.     rt_set_errno(-RT_ENOSYS);
    338.     return 0;
    339. }

    340. static rt_size_t rt_at32_emac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
    341. {
    342.     LOG_D("emac write");
    343.     rt_set_errno(-RT_ENOSYS);
    344.     return 0;
    345. }

    346. static rt_err_t rt_at32_emac_control(rt_device_t dev, int cmd, void *args)
    347. {
    348.     switch (cmd)
    349.     {
    350.     case NIOCTL_GADDR:
    351.         /* get mac address */
    352.         if (args)
    353.         {
    354.             SMEMCPY(args, at32_emac_device.dev_addr, 6);
    355.         }
    356.         else
    357.         {
    358.             return -RT_ERROR;
    359.         }
    360.         break;

    361.     default :
    362.         break;
    363.     }

    364.     return RT_EOK;
    365. }

    366. /**
    367.   * @brief transmit data
    368.   */
    369. rt_err_t rt_at32_emac_tx(rt_device_t dev, struct pbuf *p)
    370. {
    371.     struct pbuf *q;
    372.     rt_uint32_t offset;

    373.     while ((dma_tx_desc_to_set->status & EMAC_DMATXDESC_OWN) != RESET)
    374.     {
    375.         rt_err_t result;
    376.         rt_uint32_t level;

    377.         level = rt_hw_interrupt_disable();
    378.         tx_is_waiting = RT_TRUE;
    379.         rt_hw_interrupt_enable(level);

    380.         /* it's own bit set, wait it */
    381.         result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER);
    382.         if (result == RT_EOK) break;
    383.         if (result == -RT_ERROR) return -RT_ERROR;
    384.     }

    385.     offset = 0;
    386.     for (q = p; q != NULL; q = q->next)
    387.     {
    388.         uint8_t *buffer;

    389.         /* copy the frame to be sent into memory pointed by the current ethernet dma tx descriptor */
    390.         buffer = (uint8_t*)((dma_tx_desc_to_set->buf1addr) + offset);
    391.         SMEMCPY(buffer, q->payload, q->len);
    392.         offset += q->len;
    393.     }

    394. #ifdef EMAC_TX_DUMP
    395.     dump_hex(p->payload, p->tot_len);
    396. #endif
    397.     /* prepare transmit descriptors to give to dma */
    398.     LOG_D("transmit frame length :%d", p->tot_len);

    399.     /* setting the frame length: bits[12:0] */
    400.     dma_tx_desc_to_set->controlsize = (p->tot_len & EMAC_DMATXDESC_TBS1);
    401.     /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
    402.     dma_tx_desc_to_set->status |= EMAC_DMATXDESC_LS | EMAC_DMATXDESC_FS;
    403.     /* enable tx completion interrupt */
    404.     dma_tx_desc_to_set->status |= EMAC_DMATXDESC_IC;
    405.     /* set own bit of the tx descriptor status: gives the buffer back to ethernet dma */
    406.     dma_tx_desc_to_set->status |= EMAC_DMATXDESC_OWN;

    407.     /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
    408.     if(emac_dma_flag_get(EMAC_DMA_TBU_FLAG) != RESET)
    409.     {
    410.         emac_dma_flag_clear(EMAC_DMA_TBU_FLAG);
    411.         emac_dma_poll_demand_set(EMAC_DMA_TRANSMIT, 0);
    412.     }

    413.     /* selects the next dma tx descriptor list for next buffer to send */
    414.     dma_tx_desc_to_set = (emac_dma_desc_type*) (dma_tx_desc_to_set->buf2nextdescaddr);

    415.     return ERR_OK;
    416. }

    417. /**
    418.   * @brief receive data
    419.   */
    420. struct pbuf *rt_at32_emac_rx(rt_device_t dev)
    421. {
    422.     struct pbuf *p = NULL;
    423.     struct pbuf *q = NULL;
    424.     rt_uint32_t offset = 0;
    425.     uint16_t len = 0;
    426.     uint8_t *buffer;

    427.     /* get received frame */
    428.     len = emac_received_packet_size_get();
    429.     if(len > 0)
    430.     {
    431.         LOG_D("receive frame len : %d", len);
    432.         /* we allocate a pbuf chain of pbufs from the lwip buffer pool */
    433.         p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

    434.         if(p != NULL)
    435.         {
    436.             for (q = p; q != RT_NULL; q= q->next)
    437.             {
    438.                 /* get rx buffer */
    439.                 buffer = (uint8_t *)(dma_rx_desc_to_get->buf1addr);
    440. #ifdef EMAC_RX_DUMP
    441.                 dump_hex(buffer, len);
    442. #endif
    443.                 /* copy the received frame into buffer from memory pointed by the current ethernet dma rx descriptor */
    444.                 SMEMCPY(q->payload, (buffer + offset), q->len);
    445.                 offset += q->len;
    446.             }
    447.         }
    448.     }
    449.     else
    450.     {
    451.         return p;
    452.     }

    453.     /* release descriptors to dma */
    454.     dma_rx_desc_to_get->status |= EMAC_DMARXDESC_OWN;

    455.     /* when rx buffer unavailable flag is set: clear it and resume reception */
    456.     if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG) != RESET)
    457.     {
    458.         /* clear rbu ethernet dma flag */
    459.         emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
    460.         /* resume dma reception */
    461.         emac_dma_poll_demand_set(EMAC_DMA_RECEIVE, 0);
    462.     }

    463.     /* update the ethernet dma global rx descriptor with next rx decriptor */
    464.     /* chained mode */
    465.     if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RCH) != RESET)
    466.     {
    467.         /* selects the next dma rx descriptor list for next buffer to read */
    468.         dma_rx_desc_to_get = (emac_dma_desc_type*) (dma_rx_desc_to_get->buf2nextdescaddr);
    469.     }
    470.     /* ring mode */
    471.     else
    472.     {
    473.         if((dma_rx_desc_to_get->controlsize & EMAC_DMARXDESC_RER) != RESET)
    474.         {
    475.             /* selects the first dma rx descriptor for next buffer to read: last rx descriptor was used */
    476.             dma_rx_desc_to_get = (emac_dma_desc_type*) (EMAC_DMA->rdladdr);
    477.         }
    478.         else
    479.         {
    480.             /* selects the next dma rx descriptor list for next buffer to read */
    481.             dma_rx_desc_to_get = (emac_dma_desc_type*) ((uint32_t)dma_rx_desc_to_get + 0x10 + ((EMAC_DMA->bm & 0x0000007C) >> 2));
    482.         }
    483.     }
    484.     return p;
    485. }

    486. void EMAC_IRQHandler(void)
    487. {
    488.     /* enter interrupt */
    489.     rt_interrupt_enter();

    490.     /* clear received it */
    491.     if(emac_dma_flag_get(EMAC_DMA_NIS_FLAG) != RESET)
    492.     {
    493.         emac_dma_flag_clear(EMAC_DMA_NIS_FLAG);
    494.     }
    495.     if(emac_dma_flag_get(EMAC_DMA_AIS_FLAG) != RESET)
    496.     {
    497.         emac_dma_flag_clear(EMAC_DMA_AIS_FLAG);
    498.     }
    499.     if(emac_dma_flag_get(EMAC_DMA_OVF_FLAG) != RESET)
    500.     {
    501.         emac_dma_flag_clear(EMAC_DMA_OVF_FLAG);
    502.     }
    503.     if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG) != RESET)
    504.     {
    505.         emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
    506.     }

    507.     /* packet receiption */
    508.     if (emac_dma_flag_get(EMAC_DMA_RI_FLAG) == SET)
    509.     {
    510.         /* a frame has been received */
    511.         eth_device_ready(&(at32_emac_device.parent));
    512.         emac_dma_flag_clear(EMAC_DMA_RI_FLAG);
    513.     }

    514.     /* packet transmission */
    515.     if (emac_dma_flag_get(EMAC_DMA_TI_FLAG) == SET)
    516.     {
    517.         if (tx_is_waiting == RT_TRUE)
    518.         {
    519.             tx_is_waiting = RT_FALSE;
    520.             rt_sem_release(&tx_wait);
    521.         }

    522.         emac_dma_flag_clear(EMAC_DMA_TI_FLAG);
    523.     }

    524.     /* leave interrupt */
    525.     rt_interrupt_leave();
    526. }

    527. enum {
    528.     PHY_LINK        = (1 << 0),
    529.     PHY_10M         = (1 << 1),
    530.     PHY_FULLDUPLEX  = (1 << 2),
    531. };

    532. static void phy_linkchange()
    533. {
    534.     static rt_uint8_t phy_speed = 0;
    535.     rt_uint8_t phy_speed_new = 0;
    536.     rt_uint16_t status;

    537.     emac_phy_register_read(phy_addr, PHY_BASIC_STATUS_REG, (uint16_t *)&status);
    538.     LOG_D("phy basic status reg is 0x%X", status);

    539.     if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
    540.     {
    541.         rt_uint16_t SR = 0;

    542.         phy_speed_new |= PHY_LINK;

    543.         emac_phy_register_read(phy_addr, PHY_SPECIFIED_CS_REG, (uint16_t *)&SR);
    544.         LOG_D("phy control status reg is 0x%X", SR);

    545.         if (SR & (PHY_SPEED_MODE))
    546.         {
    547.             phy_speed_new |= PHY_10M;
    548.         }

    549.         if (SR & (PHY_DUPLEX_MODE))
    550.         {
    551.             phy_speed_new |= PHY_FULLDUPLEX;
    552.         }
    553.     }

    554.     if (phy_speed != phy_speed_new)
    555.     {
    556.         phy_speed = phy_speed_new;
    557.         if (phy_speed & PHY_LINK)
    558.         {
    559.             LOG_D("link up");
    560.             if (phy_speed & PHY_10M)
    561.             {
    562.                 LOG_D("10Mbps");
    563.                 at32_emac_device.emac_speed = EMAC_SPEED_10MBPS;
    564.             }
    565.             else
    566.             {
    567.                 at32_emac_device.emac_speed = EMAC_SPEED_100MBPS;
    568.                 LOG_D("100Mbps");
    569.             }

    570.             if (phy_speed & PHY_FULLDUPLEX)
    571.             {
    572.                 LOG_D("full-duplex");
    573.                 at32_emac_device.emac_mode = EMAC_FULL_DUPLEX;
    574.             }
    575.             else
    576.             {
    577.                 LOG_D("half-duplex");
    578.                 at32_emac_device.emac_mode = EMAC_HALF_DUPLEX;
    579.             }

    580.             /* send link up. */
    581.             eth_device_linkchange(&at32_emac_device.parent, RT_TRUE);
    582.         }
    583.         else
    584.         {
    585.             LOG_I("link down");
    586.             eth_device_linkchange(&at32_emac_device.parent, RT_FALSE);
    587.         }
    588.     }
    589. }

    590. #ifdef PHY_USING_INTERRUPT_MODE
    591. static void emac_phy_isr(void *args)
    592. {
    593.     rt_uint32_t status = 0;

    594.     emac_phy_register_read(phy_addr, PHY_INTERRUPT_FLAG_REG, (uint16_t *)&status);
    595.     LOG_D("phy interrupt status reg is 0x%X", status);

    596.     phy_linkchange();
    597. }
    598. #endif /* PHY_USING_INTERRUPT_MODE */

    599. static void phy_monitor_thread_entry(void *parameter)
    600. {
    601.     uint8_t detected_count = 0;

    602.     while(phy_addr == 0xFF)
    603.     {
    604.         /* phy search */
    605.         rt_uint32_t i, temp;
    606.         for (i = 0; i <= 0x1F; i++)
    607.         {
    608.             emac_phy_register_read(i, PHY_BASIC_STATUS_REG, (uint16_t *)&temp);

    609.             if (temp != 0xFFFF && temp != 0x00)
    610.             {
    611.                 phy_addr = i;
    612.                 break;
    613.             }
    614.         }

    615.         detected_count++;
    616.         rt_thread_mdelay(1000);

    617.         if (detected_count > 10)
    618.         {
    619.             LOG_E("No PHY device was detected, please check hardware!");
    620.         }
    621.     }

    622.     LOG_D("Found a phy, address:0x%02X", phy_addr);

    623.     /* reset phy */
    624.     LOG_D("RESET PHY!");
    625.     emac_phy_register_write(phy_addr, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
    626.     rt_thread_mdelay(2000);
    627.     emac_phy_register_write(phy_addr, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);

    628.     phy_linkchange();
    629. #ifdef PHY_USING_INTERRUPT_MODE
    630.     /* configuration intterrupt pin */
    631.     rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
    632.     rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, emac_phy_isr, (void *)"callbackargs");
    633.     rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);

    634.     /* enable phy interrupt */
    635.     emac_phy_register_write(phy_addr, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
    636. #if defined(PHY_INTERRUPT_CTRL_REG)
    637.     emac_phy_register_write(phy_addr, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
    638. #endif
    639. #else /* PHY_USING_INTERRUPT_MODE */
    640.     at32_emac_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
    641.                                         NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
    642.     if (!at32_emac_device.poll_link_timer || rt_timer_start(at32_emac_device.poll_link_timer) != RT_EOK)
    643.     {
    644.         LOG_E("Start link change detection timer failed");
    645.     }
    646. #endif /* PHY_USING_INTERRUPT_MODE */
    647. }

    648. extern void phy_reset(void);

    649. /* Register the EMAC device */
    650. static int rt_hw_at32_emac_init(void)
    651. {
    652.     rt_err_t state = RT_EOK;

    653.     /* Prepare receive and send buffers */
    654.     rx_buff = (rt_uint8_t *)rt_calloc(EMAC_NUM_RX_BUF, EMAC_MAX_PACKET_LENGTH);
    655.     if (rx_buff == RT_NULL)
    656.     {
    657.         LOG_E("No memory");
    658.         state = -RT_ENOMEM;
    659.         goto __exit;
    660.     }

    661.     tx_buff = (rt_uint8_t *)rt_calloc(EMAC_NUM_TX_BUF, EMAC_MAX_PACKET_LENGTH);
    662.     if (tx_buff == RT_NULL)
    663.     {
    664.         LOG_E("No memory");
    665.         state = -RT_ENOMEM;
    666.         goto __exit;
    667.     }

    668.     dma_rx_dscr_tab = (emac_dma_desc_type *)rt_calloc(EMAC_NUM_RX_BUF, sizeof(emac_dma_desc_type));
    669.     if (dma_rx_dscr_tab == RT_NULL)
    670.     {
    671.         LOG_E("No memory");
    672.         state = -RT_ENOMEM;
    673.         goto __exit;
    674.     }

    675.     dma_tx_dscr_tab = (emac_dma_desc_type *)rt_calloc(EMAC_NUM_TX_BUF, sizeof(emac_dma_desc_type));
    676.     if (dma_tx_dscr_tab == RT_NULL)
    677.     {
    678.         LOG_E("No memory");
    679.         state = -RT_ENOMEM;
    680.         goto __exit;
    681.     }

    682.     // /* phy clock */
    683.     // phy_clock_config();

    684.     /* enable periph clock */
    685.     crm_periph_clock_enable(CRM_EMAC_PERIPH_CLOCK, TRUE);
    686.     crm_periph_clock_enable(CRM_EMACTX_PERIPH_CLOCK, TRUE);
    687.     crm_periph_clock_enable(CRM_EMACRX_PERIPH_CLOCK, TRUE);

    688.     /* interface mode */
    689. #if defined (SOC_SERIES_AT32F407)
    690.     gpio_pin_remap_config(MII_RMII_SEL_GMUX, TRUE);
    691. #endif
    692. #if defined (SOC_SERIES_AT32F437)
    693.     scfg_emac_interface_set(SCFG_EMAC_SELECT_RMII);
    694. #endif

    695.     /* emac gpio init */
    696.     at32_msp_emac_init(NULL);

    697.     at32_emac_device.emac_speed = EMAC_SPEED_100MBPS;
    698.     at32_emac_device.emac_mode  = EMAC_FULL_DUPLEX;

    699.     at32_emac_device.dev_addr[0] = 0x00;
    700.     at32_emac_device.dev_addr[1] = 0x66;
    701.     at32_emac_device.dev_addr[2] = 0x88;
    702.     /* generate mac addr from unique id (only for test). */
    703.     at32_emac_device.dev_addr[3] = *(rt_uint8_t *)(0x1FFFF7E8 + 4);
    704.     at32_emac_device.dev_addr[4] = *(rt_uint8_t *)(0x1FFFF7E8 + 2);
    705.     at32_emac_device.dev_addr[5] = *(rt_uint8_t *)(0x1FFFF7E8 + 0);

    706.     at32_emac_device.parent.parent.init = rt_at32_emac_init;
    707.     at32_emac_device.parent.parent.open = rt_at32_emac_open;
    708.     at32_emac_device.parent.parent.close = rt_at32_emac_close;
    709.     at32_emac_device.parent.parent.read = rt_at32_emac_read;
    710.     at32_emac_device.parent.parent.write = rt_at32_emac_write;
    711.     at32_emac_device.parent.parent.control = rt_at32_emac_control;
    712.     at32_emac_device.parent.parent.user_data = RT_NULL;

    713.     at32_emac_device.parent.eth_rx = rt_at32_emac_rx;
    714.     at32_emac_device.parent.eth_tx = rt_at32_emac_tx;

    715.     /* reset phy */
    716.     phy_reset();
    717.     rt_thread_mdelay(2000);

    718.     /* start phy monitor */
    719.     rt_thread_t tid;
    720.     tid = rt_thread_create("phy",
    721.                            phy_monitor_thread_entry,
    722.                            RT_NULL,
    723.                            1024,
    724.                            RT_THREAD_PRIORITY_MAX - 2,
    725.                            2);
    726.     if (tid != RT_NULL)
    727.     {
    728.         rt_thread_startup(tid);
    729.     }
    730.     else
    731.     {
    732.         state = -RT_ERROR;
    733.     }

    734.     /* register eth device */
    735.     state = eth_device_init(&(at32_emac_device.parent), "e0");
    736.     if (RT_EOK == state)
    737.     {
    738.         LOG_D("emac device init success");
    739.     }
    740.     else
    741.     {
    742.         LOG_E("emac device init faild: %d", state);
    743.         state = -RT_ERROR;
    744.         goto __exit;
    745.     }
    746. __exit:
    747.     if (state != RT_EOK)
    748.     {
    749.         if (rx_buff)
    750.         {
    751.             rt_free(rx_buff);
    752.         }

    753.         if (tx_buff)
    754.         {
    755.             rt_free(tx_buff);
    756.         }

    757.         if (dma_rx_dscr_tab)
    758.         {
    759.             rt_free(dma_rx_dscr_tab);
    760.         }

    761.         if (dma_tx_dscr_tab)
    762.         {
    763.             rt_free(dma_tx_dscr_tab);
    764.         }
    765.     }

    766.     return state;
    767. }

    768. INIT_DEVICE_EXPORT(rt_hw_at32_emac_init);


     
diaos 发表于 2023-3-29 13:28 | 显示全部楼层
雅特力的例程
我没有找到lan8720a 的例程,楼主方便提供下不
muyichuan2012 发表于 2023-3-30 10:38 | 显示全部楼层
本帖最后由 muyichuan2012 于 2023-3-30 10:39 编辑

如附件,示例代码演示AT32F407/437 EMAC接不同PHY配置方法使用方法。如下型号PHY已打通

DM9162DP83848C
LAN8720A
AR8032
IP101GR
RTL8201F
YT8512
IP175LL
IP179N


SC0073_AT32F407_437_EMAC_Connected_with_Different_PHY_V2.0.3 (1).zip

9.01 MB, 下载次数: 20

评论

可以  发表于 2024-7-9 11:22
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

9

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部