1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include <stdbool.h> 17 #include "esp_eth_com.h" 18 #include "sdkconfig.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /** 25 * @brief Ethernet MAC 26 * 27 */ 28 typedef struct esp_eth_mac_s esp_eth_mac_t; 29 30 /** 31 * @brief Ethernet MAC 32 * 33 */ 34 struct esp_eth_mac_s { 35 /** 36 * @brief Set mediator for Ethernet MAC 37 * 38 * @param[in] mac: Ethernet MAC instance 39 * @param[in] eth: Ethernet mediator 40 * 41 * @return 42 * - ESP_OK: set mediator for Ethernet MAC successfully 43 * - ESP_ERR_INVALID_ARG: set mediator for Ethernet MAC failed because of invalid argument 44 * 45 */ 46 esp_err_t (*set_mediator)(esp_eth_mac_t *mac, esp_eth_mediator_t *eth); 47 48 /** 49 * @brief Initialize Ethernet MAC 50 * 51 * @param[in] mac: Ethernet MAC instance 52 * 53 * @return 54 * - ESP_OK: initialize Ethernet MAC successfully 55 * - ESP_ERR_TIMEOUT: initialize Ethernet MAC failed because of timeout 56 * - ESP_FAIL: initialize Ethernet MAC failed because some other error occurred 57 * 58 */ 59 esp_err_t (*init)(esp_eth_mac_t *mac); 60 61 /** 62 * @brief Deinitialize Ethernet MAC 63 * 64 * @param[in] mac: Ethernet MAC instance 65 * 66 * @return 67 * - ESP_OK: deinitialize Ethernet MAC successfully 68 * - ESP_FAIL: deinitialize Ethernet MAC failed because some error occurred 69 * 70 */ 71 esp_err_t (*deinit)(esp_eth_mac_t *mac); 72 73 /** 74 * @brief Start Ethernet MAC 75 * 76 * @param[in] mac: Ethernet MAC instance 77 * 78 * @return 79 * - ESP_OK: start Ethernet MAC successfully 80 * - ESP_FAIL: start Ethernet MAC failed because some other error occurred 81 * 82 */ 83 esp_err_t (*start)(esp_eth_mac_t *mac); 84 85 /** 86 * @brief Stop Ethernet MAC 87 * 88 * @param[in] mac: Ethernet MAC instance 89 * 90 * @return 91 * - ESP_OK: stop Ethernet MAC successfully 92 * - ESP_FAIL: stop Ethernet MAC failed because some error occurred 93 * 94 */ 95 esp_err_t (*stop)(esp_eth_mac_t *mac); 96 97 /** 98 * @brief Transmit packet from Ethernet MAC 99 * 100 * @param[in] mac: Ethernet MAC instance 101 * @param[in] buf: packet buffer to transmit 102 * @param[in] length: length of packet 103 * 104 * @return 105 * - ESP_OK: transmit packet successfully 106 * - ESP_ERR_INVALID_ARG: transmit packet failed because of invalid argument 107 * - ESP_ERR_INVALID_STATE: transmit packet failed because of wrong state of MAC 108 * - ESP_FAIL: transmit packet failed because some other error occurred 109 * 110 */ 111 esp_err_t (*transmit)(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length); 112 113 /** 114 * @brief Receive packet from Ethernet MAC 115 * 116 * @param[in] mac: Ethernet MAC instance 117 * @param[out] buf: packet buffer which will preserve the received frame 118 * @param[out] length: length of the received packet 119 * 120 * @note Memory of buf is allocated in the Layer2, make sure it get free after process. 121 * @note Before this function got invoked, the value of "length" should set by user, equals the size of buffer. 122 * After the function returned, the value of "length" means the real length of received data. 123 * 124 * @return 125 * - ESP_OK: receive packet successfully 126 * - ESP_ERR_INVALID_ARG: receive packet failed because of invalid argument 127 * - ESP_ERR_INVALID_SIZE: input buffer size is not enough to hold the incoming data. 128 * in this case, value of returned "length" indicates the real size of incoming data. 129 * - ESP_FAIL: receive packet failed because some other error occurred 130 * 131 */ 132 esp_err_t (*receive)(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length); 133 134 /** 135 * @brief Read PHY register 136 * 137 * @param[in] mac: Ethernet MAC instance 138 * @param[in] phy_addr: PHY chip address (0~31) 139 * @param[in] phy_reg: PHY register index code 140 * @param[out] reg_value: PHY register value 141 * 142 * @return 143 * - ESP_OK: read PHY register successfully 144 * - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument 145 * - ESP_ERR_INVALID_STATE: read PHY register failed because of wrong state of MAC 146 * - ESP_ERR_TIMEOUT: read PHY register failed because of timeout 147 * - ESP_FAIL: read PHY register failed because some other error occurred 148 * 149 */ 150 esp_err_t (*read_phy_reg)(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value); 151 152 /** 153 * @brief Write PHY register 154 * 155 * @param[in] mac: Ethernet MAC instance 156 * @param[in] phy_addr: PHY chip address (0~31) 157 * @param[in] phy_reg: PHY register index code 158 * @param[in] reg_value: PHY register value 159 * 160 * @return 161 * - ESP_OK: write PHY register successfully 162 * - ESP_ERR_INVALID_STATE: write PHY register failed because of wrong state of MAC 163 * - ESP_ERR_TIMEOUT: write PHY register failed because of timeout 164 * - ESP_FAIL: write PHY register failed because some other error occurred 165 * 166 */ 167 esp_err_t (*write_phy_reg)(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value); 168 169 /** 170 * @brief Set MAC address 171 * 172 * @param[in] mac: Ethernet MAC instance 173 * @param[in] addr: MAC address 174 * 175 * @return 176 * - ESP_OK: set MAC address successfully 177 * - ESP_ERR_INVALID_ARG: set MAC address failed because of invalid argument 178 * - ESP_FAIL: set MAC address failed because some other error occurred 179 * 180 */ 181 esp_err_t (*set_addr)(esp_eth_mac_t *mac, uint8_t *addr); 182 183 /** 184 * @brief Get MAC address 185 * 186 * @param[in] mac: Ethernet MAC instance 187 * @param[out] addr: MAC address 188 * 189 * @return 190 * - ESP_OK: get MAC address successfully 191 * - ESP_ERR_INVALID_ARG: get MAC address failed because of invalid argument 192 * - ESP_FAIL: get MAC address failed because some other error occurred 193 * 194 */ 195 esp_err_t (*get_addr)(esp_eth_mac_t *mac, uint8_t *addr); 196 197 /** 198 * @brief Set speed of MAC 199 * 200 * @param[in] ma:c Ethernet MAC instance 201 * @param[in] speed: MAC speed 202 * 203 * @return 204 * - ESP_OK: set MAC speed successfully 205 * - ESP_ERR_INVALID_ARG: set MAC speed failed because of invalid argument 206 * - ESP_FAIL: set MAC speed failed because some other error occurred 207 * 208 */ 209 esp_err_t (*set_speed)(esp_eth_mac_t *mac, eth_speed_t speed); 210 211 /** 212 * @brief Set duplex mode of MAC 213 * 214 * @param[in] mac: Ethernet MAC instance 215 * @param[in] duplex: MAC duplex 216 * 217 * @return 218 * - ESP_OK: set MAC duplex mode successfully 219 * - ESP_ERR_INVALID_ARG: set MAC duplex failed because of invalid argument 220 * - ESP_FAIL: set MAC duplex failed because some other error occurred 221 * 222 */ 223 esp_err_t (*set_duplex)(esp_eth_mac_t *mac, eth_duplex_t duplex); 224 225 /** 226 * @brief Set link status of MAC 227 * 228 * @param[in] mac: Ethernet MAC instance 229 * @param[in] link: Link status 230 * 231 * @return 232 * - ESP_OK: set link status successfully 233 * - ESP_ERR_INVALID_ARG: set link status failed because of invalid argument 234 * - ESP_FAIL: set link status failed because some other error occurred 235 * 236 */ 237 esp_err_t (*set_link)(esp_eth_mac_t *mac, eth_link_t link); 238 239 /** 240 * @brief Set promiscuous of MAC 241 * 242 * @param[in] mac: Ethernet MAC instance 243 * @param[in] enable: set true to enable promiscuous mode; set false to disable promiscuous mode 244 * 245 * @return 246 * - ESP_OK: set promiscuous mode successfully 247 * - ESP_FAIL: set promiscuous mode failed because some error occurred 248 * 249 */ 250 esp_err_t (*set_promiscuous)(esp_eth_mac_t *mac, bool enable); 251 252 /** 253 * @brief Enable flow control on MAC layer or not 254 * 255 * @param[in] mac: Ethernet MAC instance 256 * @param[in] enable: set true to enable flow control; set false to disable flow control 257 * 258 * @return 259 * - ESP_OK: set flow control successfully 260 * - ESP_FAIL: set flow control failed because some error occurred 261 * 262 */ 263 esp_err_t (*enable_flow_ctrl)(esp_eth_mac_t *mac, bool enable); 264 265 /** 266 * @brief Set the PAUSE ability of peer node 267 * 268 * @param[in] mac: Ethernet MAC instance 269 * @param[in] ability: zero indicates that pause function is supported by link partner; non-zero indicates that pause function is not supported by link partner 270 * 271 * @return 272 * - ESP_OK: set peer pause ability successfully 273 * - ESP_FAIL: set peer pause ability failed because some error occurred 274 */ 275 esp_err_t (*set_peer_pause_ability)(esp_eth_mac_t *mac, uint32_t ability); 276 277 /** 278 * @brief Free memory of Ethernet MAC 279 * 280 * @param[in] mac: Ethernet MAC instance 281 * 282 * @return 283 * - ESP_OK: free Ethernet MAC instance successfully 284 * - ESP_FAIL: free Ethernet MAC instance failed because some error occurred 285 * 286 */ 287 esp_err_t (*del)(esp_eth_mac_t *mac); 288 }; 289 290 /** 291 * @brief RMII Clock Mode Options 292 * 293 */ 294 typedef enum { 295 /** 296 * @brief Default values configured using Kconfig are going to be used when "Default" selected. 297 * 298 */ 299 EMAC_CLK_DEFAULT, 300 301 /** 302 * @brief Input RMII Clock from external. EMAC Clock GPIO number needs to be configured when this option is selected. 303 * 304 * @note MAC will get RMII clock from outside. Note that ESP32 only supports GPIO0 to input the RMII clock. 305 * 306 */ 307 EMAC_CLK_EXT_IN, 308 309 /** 310 * @brief Output RMII Clock from internal APLL Clock. EMAC Clock GPIO number needs to be configured when this option is selected. 311 * 312 */ 313 EMAC_CLK_OUT 314 } emac_rmii_clock_mode_t; 315 316 /** 317 * @brief RMII Clock GPIO number Options 318 * 319 */ 320 typedef enum { 321 /** 322 * @brief MAC will get RMII clock from outside at this GPIO. 323 * 324 * @note ESP32 only supports GPIO0 to input the RMII clock. 325 * 326 */ 327 EMAC_CLK_IN_GPIO = 0, 328 329 /** 330 * @brief Output RMII Clock from internal APLL Clock available at GPIO0 331 * 332 * @note GPIO0 can be set to output a pre-divided PLL clock (test only!). Enabling this option will configure GPIO0 to output a 50MHz clock. 333 * In fact this clock doesn’t have directly relationship with EMAC peripheral. Sometimes this clock won’t work well with your PHY chip. 334 * You might need to add some extra devices after GPIO0 (e.g. inverter). Note that outputting RMII clock on GPIO0 is an experimental practice. 335 * If you want the Ethernet to work with WiFi, don’t select GPIO0 output mode for stability. 336 * 337 */ 338 EMAC_APPL_CLK_OUT_GPIO = 0, 339 340 /** 341 * @brief Output RMII Clock from internal APLL Clock available at GPIO16 342 * 343 */ 344 EMAC_CLK_OUT_GPIO = 16, 345 346 /** 347 * @brief Inverted Output RMII Clock from internal APLL Clock available at GPIO17 348 * 349 */ 350 EMAC_CLK_OUT_180_GPIO = 17 351 } emac_rmii_clock_gpio_t; 352 353 /** 354 * @brief Ethernet MAC Clock Configuration 355 * 356 */ 357 typedef union { 358 struct { 359 // MII interface is not fully implemented... 360 // Reserved for GPIO number, clock source, etc. in MII mode 361 } mii; /*!< EMAC MII Clock Configuration */ 362 struct { 363 emac_rmii_clock_mode_t clock_mode; /*!< RMII Clock Mode Configuration */ 364 emac_rmii_clock_gpio_t clock_gpio; /*!< RMII Clock GPIO Configuration */ 365 } rmii; /*!< EMAC RMII Clock Configuration */ 366 } eth_mac_clock_config_t; 367 368 369 /** 370 * @brief Configuration of Ethernet MAC object 371 * 372 */ 373 typedef struct { 374 uint32_t sw_reset_timeout_ms; /*!< Software reset timeout value (Unit: ms) */ 375 uint32_t rx_task_stack_size; /*!< Stack size of the receive task */ 376 uint32_t rx_task_prio; /*!< Priority of the receive task */ 377 int smi_mdc_gpio_num; /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */ 378 int smi_mdio_gpio_num; /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */ 379 uint32_t flags; /*!< Flags that specify extra capability for mac driver */ 380 eth_data_interface_t interface; /*!< EMAC Data interface to PHY (MII/RMII) */ 381 eth_mac_clock_config_t clock_config; /*!< EMAC Interface clock configuration */ 382 } eth_mac_config_t; 383 384 #define ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE (1 << 0) /*!< MAC driver can work when cache is disabled */ 385 #define ETH_MAC_FLAG_PIN_TO_CORE (1 << 1) /*!< Pin MAC task to the CPU core where driver installation happened */ 386 387 /** 388 * @brief Default configuration for Ethernet MAC object 389 * 390 */ 391 #define ETH_MAC_DEFAULT_CONFIG() \ 392 { \ 393 .sw_reset_timeout_ms = 100, \ 394 .rx_task_stack_size = 2048, \ 395 .rx_task_prio = 15, \ 396 .smi_mdc_gpio_num = 23, \ 397 .smi_mdio_gpio_num = 18, \ 398 .flags = 0, \ 399 .interface = EMAC_DATA_INTERFACE_RMII, \ 400 .clock_config = \ 401 { \ 402 .rmii = \ 403 { \ 404 .clock_mode = EMAC_CLK_DEFAULT, \ 405 .clock_gpio = EMAC_CLK_IN_GPIO \ 406 } \ 407 } \ 408 } 409 410 #if CONFIG_ETH_USE_ESP32_EMAC 411 /** 412 * @brief Create ESP32 Ethernet MAC instance 413 * 414 * @param config: Ethernet MAC configuration 415 * 416 * @return 417 * - instance: create MAC instance successfully 418 * - NULL: create MAC instance failed because some error occurred 419 */ 420 esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config); 421 #endif // CONFIG_ETH_USE_ESP32_EMAC 422 423 #if CONFIG_ETH_SPI_ETHERNET_DM9051 424 /** 425 * @brief DM9051 specific configuration 426 * 427 */ 428 typedef struct { 429 void *spi_hdl; /*!< Handle of SPI device driver */ 430 int int_gpio_num; /*!< Interrupt GPIO number */ 431 } eth_dm9051_config_t; 432 433 /** 434 * @brief Default DM9051 specific configuration 435 * 436 */ 437 #define ETH_DM9051_DEFAULT_CONFIG(spi_device) \ 438 { \ 439 .spi_hdl = spi_device, \ 440 .int_gpio_num = 4, \ 441 } 442 443 /** 444 * @brief Create DM9051 Ethernet MAC instance 445 * 446 * @param dm9051_config: DM9051 specific configuration 447 * @param mac_config: Ethernet MAC configuration 448 * 449 * @return 450 * - instance: create MAC instance successfully 451 * - NULL: create MAC instance failed because some error occurred 452 */ 453 esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config); 454 #endif // CONFIG_ETH_SPI_ETHERNET_DM9051 455 456 #if CONFIG_ETH_SPI_ETHERNET_W5500 457 /** 458 * @brief W5500 specific configuration 459 * 460 */ 461 typedef struct { 462 void *spi_hdl; /*!< Handle of SPI device driver */ 463 int int_gpio_num; /*!< Interrupt GPIO number */ 464 } eth_w5500_config_t; 465 466 /** 467 * @brief Default W5500 specific configuration 468 * 469 */ 470 #define ETH_W5500_DEFAULT_CONFIG(spi_device) \ 471 { \ 472 .spi_hdl = spi_device, \ 473 .int_gpio_num = 4, \ 474 } 475 476 /** 477 * @brief Create W5500 Ethernet MAC instance 478 * 479 * @param w5500_config: W5500 specific configuration 480 * @param mac_config: Ethernet MAC configuration 481 * 482 * @return 483 * - instance: create MAC instance successfully 484 * - NULL: create MAC instance failed because some error occurred 485 */ 486 esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, const eth_mac_config_t *mac_config); 487 #endif // CONFIG_ETH_SPI_ETHERNET_W5500 488 489 #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL 490 /** 491 * @brief KSZ8851SNL specific configuration 492 * 493 */ 494 typedef struct { 495 void *spi_hdl; /*!< Handle of SPI device driver */ 496 int int_gpio_num; /*!< Interrupt GPIO number */ 497 } eth_ksz8851snl_config_t; 498 499 /** 500 * @brief Default KSZ8851SNL specific configuration 501 * 502 */ 503 #define ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_device) \ 504 { \ 505 .spi_hdl = spi_device, \ 506 .int_gpio_num = 14, \ 507 } 508 509 /** 510 * @brief Create KSZ8851SNL Ethernet MAC instance 511 * 512 * @param ksz8851snl_config: KSZ8851SNL specific configuration 513 * @param mac_config: Ethernet MAC configuration 514 * 515 * @return 516 * - instance: create MAC instance successfully 517 * - NULL: create MAC instance failed because some error occurred 518 */ 519 esp_eth_mac_t *esp_eth_mac_new_ksz8851snl(const eth_ksz8851snl_config_t *ksz8851snl_config, const eth_mac_config_t *mac_config); 520 #endif // CONFIG_ETH_SPI_ETHERNET_KSZ8851 521 522 #if CONFIG_ETH_USE_OPENETH 523 /** 524 * @brief Create OpenCores Ethernet MAC instance 525 * 526 * @param config: Ethernet MAC configuration 527 * 528 * @return 529 * - instance: create MAC instance successfully 530 * - NULL: create MAC instance failed because some error occurred 531 */ 532 esp_eth_mac_t *esp_eth_mac_new_openeth(const eth_mac_config_t *config); 533 #endif // CONFIG_ETH_USE_OPENETH 534 535 #ifdef __cplusplus 536 } 537 #endif 538