esp_eth_mac_esp32.c
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 #include <string.h> 15 #include <stdlib.h> 16 #include <sys/cdefs.h> 17 #include "driver/periph_ctrl.h" 18 #include "driver/gpio.h" 19 #include "esp_attr.h" 20 #include "esp_log.h" 21 #include "esp_eth.h" 22 #include "esp_pm.h" 23 #include "esp_system.h" 24 #include "esp_heap_caps.h" 25 #include "esp_intr_alloc.h" 26 #include "freertos/FreeRTOS.h" 27 #include "freertos/task.h" 28 #include "freertos/semphr.h" 29 #include "hal/cpu_hal.h" 30 #include "hal/emac.h" 31 #include "soc/soc.h" 32 #include "sdkconfig.h" 33 #include "esp_rom_gpio.h" 34 #include "esp_rom_sys.h" 35 36 static const char *TAG = "emac_esp32"; 37 #define MAC_CHECK(a, str, goto_tag, ret_value, ...) \ 38 do \ 39 { \ 40 if (!(a)) \ 41 { \ 42 ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 43 ret = ret_value; \ 44 goto goto_tag; \ 45 } \ 46 } while (0) 47 48 #define PHY_OPERATION_TIMEOUT_US (1000) 49 50 #define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3) 51 #define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2) 52 53 typedef struct { 54 esp_eth_mac_t parent; 55 esp_eth_mediator_t *eth; 56 emac_hal_context_t hal; 57 intr_handle_t intr_hdl; 58 TaskHandle_t rx_task_hdl; 59 uint32_t sw_reset_timeout_ms; 60 uint32_t frames_remain; 61 uint32_t free_rx_descriptor; 62 uint32_t flow_control_high_water_mark; 63 uint32_t flow_control_low_water_mark; 64 int smi_mdc_gpio_num; 65 int smi_mdio_gpio_num; 66 uint8_t addr[6]; 67 uint8_t *rx_buf[CONFIG_ETH_DMA_RX_BUFFER_NUM]; 68 uint8_t *tx_buf[CONFIG_ETH_DMA_TX_BUFFER_NUM]; 69 bool isr_need_yield; 70 bool flow_ctrl_enabled; // indicates whether the user want to do flow control 71 bool do_flow_ctrl; // indicates whether we need to do software flow control 72 #ifdef CONFIG_PM_ENABLE 73 esp_pm_lock_handle_t pm_lock; 74 #endif 75 } emac_esp32_t; 76 77 static esp_err_t emac_esp32_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth) 78 { 79 esp_err_t ret = ESP_OK; 80 MAC_CHECK(eth, "can't set mac's mediator to null", err, ESP_ERR_INVALID_ARG); 81 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 82 emac->eth = eth; 83 return ESP_OK; 84 err: 85 return ret; 86 } 87 88 static esp_err_t emac_esp32_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value) 89 { 90 esp_err_t ret = ESP_OK; 91 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 92 MAC_CHECK(!emac_hal_is_mii_busy(&emac->hal), "phy is busy", err, ESP_ERR_INVALID_STATE); 93 emac_hal_set_phy_data(&emac->hal, reg_value); 94 emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, true); 95 /* polling the busy flag */ 96 uint32_t to = 0; 97 bool busy = true; 98 do { 99 esp_rom_delay_us(100); 100 busy = emac_hal_is_mii_busy(&emac->hal); 101 to += 100; 102 } while (busy && to < PHY_OPERATION_TIMEOUT_US); 103 MAC_CHECK(!busy, "phy is busy", err, ESP_ERR_TIMEOUT); 104 return ESP_OK; 105 err: 106 return ret; 107 } 108 109 static esp_err_t emac_esp32_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value) 110 { 111 esp_err_t ret = ESP_OK; 112 MAC_CHECK(reg_value, "can't set reg_value to null", err, ESP_ERR_INVALID_ARG); 113 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 114 MAC_CHECK(!emac_hal_is_mii_busy(&emac->hal), "phy is busy", err, ESP_ERR_INVALID_STATE); 115 emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, false); 116 /* polling the busy flag */ 117 uint32_t to = 0; 118 bool busy = true; 119 do { 120 esp_rom_delay_us(100); 121 busy = emac_hal_is_mii_busy(&emac->hal); 122 to += 100; 123 } while (busy && to < PHY_OPERATION_TIMEOUT_US); 124 MAC_CHECK(!busy, "phy is busy", err, ESP_ERR_TIMEOUT); 125 /* Store value */ 126 *reg_value = emac_hal_get_phy_data(&emac->hal); 127 return ESP_OK; 128 err: 129 return ret; 130 } 131 132 static esp_err_t emac_esp32_set_addr(esp_eth_mac_t *mac, uint8_t *addr) 133 { 134 esp_err_t ret = ESP_OK; 135 MAC_CHECK(addr, "can't set mac addr to null", err, ESP_ERR_INVALID_ARG); 136 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 137 memcpy(emac->addr, addr, 6); 138 emac_hal_set_address(&emac->hal, emac->addr); 139 return ESP_OK; 140 err: 141 return ret; 142 } 143 144 static esp_err_t emac_esp32_get_addr(esp_eth_mac_t *mac, uint8_t *addr) 145 { 146 esp_err_t ret = ESP_OK; 147 MAC_CHECK(addr, "can't set mac addr to null", err, ESP_ERR_INVALID_ARG); 148 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 149 memcpy(addr, emac->addr, 6); 150 return ESP_OK; 151 err: 152 return ret; 153 } 154 155 static esp_err_t emac_esp32_set_link(esp_eth_mac_t *mac, eth_link_t link) 156 { 157 esp_err_t ret = ESP_OK; 158 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 159 switch (link) { 160 case ETH_LINK_UP: 161 MAC_CHECK(esp_intr_enable(emac->intr_hdl) == ESP_OK, "enable interrupt failed", err, ESP_FAIL); 162 emac_hal_start(&emac->hal); 163 break; 164 case ETH_LINK_DOWN: 165 MAC_CHECK(esp_intr_disable(emac->intr_hdl) == ESP_OK, "disable interrupt failed", err, ESP_FAIL); 166 emac_hal_stop(&emac->hal); 167 break; 168 default: 169 MAC_CHECK(false, "unknown link status", err, ESP_ERR_INVALID_ARG); 170 break; 171 } 172 return ESP_OK; 173 err: 174 return ret; 175 } 176 177 static esp_err_t emac_esp32_set_speed(esp_eth_mac_t *mac, eth_speed_t speed) 178 { 179 esp_err_t ret = ESP_OK; 180 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 181 switch (speed) { 182 case ETH_SPEED_10M: 183 emac_hal_set_speed(&emac->hal, EMAC_SPEED_10M); 184 ESP_LOGD(TAG, "working in 10Mbps"); 185 break; 186 case ETH_SPEED_100M: 187 emac_hal_set_speed(&emac->hal, EMAC_SPEED_100M); 188 ESP_LOGD(TAG, "working in 100Mbps"); 189 break; 190 default: 191 MAC_CHECK(false, "unknown speed", err, ESP_ERR_INVALID_ARG); 192 break; 193 } 194 return ESP_OK; 195 err: 196 return ret; 197 } 198 199 static esp_err_t emac_esp32_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex) 200 { 201 esp_err_t ret = ESP_OK; 202 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 203 switch (duplex) { 204 case ETH_DUPLEX_HALF: 205 emac_hal_set_duplex(&emac->hal, EMAC_DUPLEX_HALF); 206 ESP_LOGD(TAG, "working in half duplex"); 207 break; 208 case ETH_DUPLEX_FULL: 209 emac_hal_set_duplex(&emac->hal, EMAC_DUPLEX_FULL); 210 ESP_LOGD(TAG, "working in full duplex"); 211 break; 212 default: 213 MAC_CHECK(false, "unknown duplex", err, ESP_ERR_INVALID_ARG); 214 break; 215 } 216 return ESP_OK; 217 err: 218 return ret; 219 } 220 221 static esp_err_t emac_esp32_set_promiscuous(esp_eth_mac_t *mac, bool enable) 222 { 223 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 224 emac_hal_set_promiscuous(&emac->hal, enable); 225 return ESP_OK; 226 } 227 228 static esp_err_t emac_esp32_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable) 229 { 230 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 231 emac->flow_ctrl_enabled = enable; 232 return ESP_OK; 233 } 234 235 static esp_err_t emac_esp32_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability) 236 { 237 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 238 // we want to enable flow control, and peer does support pause function 239 // then configure the MAC layer to enable flow control feature 240 if (emac->flow_ctrl_enabled && ability) { 241 emac_hal_enable_flow_ctrl(&emac->hal, true); 242 emac->do_flow_ctrl = true; 243 } else { 244 emac_hal_enable_flow_ctrl(&emac->hal, false); 245 emac->do_flow_ctrl = false; 246 ESP_LOGD(TAG, "Flow control not enabled for the link"); 247 } 248 return ESP_OK; 249 } 250 251 static esp_err_t emac_esp32_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length) 252 { 253 esp_err_t ret = ESP_OK; 254 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 255 uint32_t sent_len = emac_hal_transmit_frame(&emac->hal, buf, length); 256 MAC_CHECK(sent_len == length, "insufficient TX buffer size", err, ESP_ERR_INVALID_SIZE); 257 return ESP_OK; 258 err: 259 return ret; 260 } 261 262 static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length) 263 { 264 esp_err_t ret = ESP_OK; 265 uint32_t expected_len = *length; 266 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 267 MAC_CHECK(buf && length, "can't set buf and length to null", err, ESP_ERR_INVALID_ARG); 268 uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor); 269 /* we need to check the return value in case the buffer size is not enough */ 270 ESP_LOGD(TAG, "receive len= %d", receive_len); 271 MAC_CHECK(expected_len >= receive_len, "received buffer longer than expected", err, ESP_ERR_INVALID_SIZE); 272 *length = receive_len; 273 return ESP_OK; 274 err: 275 *length = expected_len; 276 return ret; 277 } 278 279 static void emac_esp32_rx_task(void *arg) 280 { 281 emac_esp32_t *emac = (emac_esp32_t *)arg; 282 uint8_t *buffer = NULL; 283 uint32_t length = 0; 284 while (1) { 285 // block indefinitely until got notification from underlay event 286 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); 287 do { 288 length = ETH_MAX_PACKET_SIZE; 289 buffer = malloc(length); 290 if (!buffer) { 291 ESP_LOGE(TAG, "no mem for receive buffer"); 292 } else if (emac_esp32_receive(&emac->parent, buffer, &length) == ESP_OK) { 293 /* pass the buffer to stack (e.g. TCP/IP layer) */ 294 if (length) { 295 emac->eth->stack_input(emac->eth, buffer, length); 296 } else { 297 free(buffer); 298 } 299 } else { 300 free(buffer); 301 } 302 // we need to do extra checking of remained frames in case there are no unhandled frames left, but pause frame is still undergoing 303 if ((emac->free_rx_descriptor < emac->flow_control_low_water_mark) && emac->do_flow_ctrl && emac->frames_remain) { 304 emac_hal_send_pause_frame(&emac->hal, true); 305 } else if ((emac->free_rx_descriptor > emac->flow_control_high_water_mark) || !emac->frames_remain) { 306 emac_hal_send_pause_frame(&emac->hal, false); 307 } 308 } while (emac->frames_remain); 309 } 310 vTaskDelete(NULL); 311 } 312 313 static void emac_esp32_init_smi_gpio(emac_esp32_t *emac) 314 { 315 if (emac->smi_mdc_gpio_num >= 0) { 316 /* Setup SMI MDC GPIO */ 317 gpio_set_direction(emac->smi_mdc_gpio_num, GPIO_MODE_OUTPUT); 318 esp_rom_gpio_connect_out_signal(emac->smi_mdc_gpio_num, EMAC_MDC_O_IDX, false, false); 319 PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[emac->smi_mdc_gpio_num], PIN_FUNC_GPIO); 320 } 321 if (emac->smi_mdio_gpio_num >= 0) { 322 /* Setup SMI MDIO GPIO */ 323 gpio_set_direction(emac->smi_mdio_gpio_num, GPIO_MODE_INPUT_OUTPUT); 324 esp_rom_gpio_connect_out_signal(emac->smi_mdio_gpio_num, EMAC_MDO_O_IDX, false, false); 325 esp_rom_gpio_connect_in_signal(emac->smi_mdio_gpio_num, EMAC_MDI_I_IDX, false); 326 PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[emac->smi_mdio_gpio_num], PIN_FUNC_GPIO); 327 } 328 } 329 330 static esp_err_t emac_esp32_init(esp_eth_mac_t *mac) 331 { 332 esp_err_t ret = ESP_OK; 333 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 334 esp_eth_mediator_t *eth = emac->eth; 335 /* enable peripheral clock */ 336 periph_module_enable(PERIPH_EMAC_MODULE); 337 /* init clock, config gpio, etc */ 338 emac_hal_lowlevel_init(&emac->hal); 339 /* init gpio used by smi interface */ 340 emac_esp32_init_smi_gpio(emac); 341 MAC_CHECK(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL) == ESP_OK, "lowlevel init failed", err, ESP_FAIL); 342 /* software reset */ 343 emac_hal_reset(&emac->hal); 344 uint32_t to = 0; 345 for (to = 0; to < emac->sw_reset_timeout_ms / 10; to++) { 346 if (emac_hal_is_reset_done(&emac->hal)) { 347 break; 348 } 349 vTaskDelay(pdMS_TO_TICKS(10)); 350 } 351 MAC_CHECK(to < emac->sw_reset_timeout_ms / 10, "reset timeout", err, ESP_ERR_TIMEOUT); 352 /* set smi clock */ 353 emac_hal_set_csr_clock_range(&emac->hal); 354 /* reset descriptor chain */ 355 emac_hal_reset_desc_chain(&emac->hal); 356 /* init mac registers by default */ 357 emac_hal_init_mac_default(&emac->hal); 358 /* init dma registers by default */ 359 emac_hal_init_dma_default(&emac->hal); 360 /* get emac address from efuse */ 361 MAC_CHECK(esp_read_mac(emac->addr, ESP_MAC_ETH) == ESP_OK, "fetch ethernet mac address failed", err, ESP_FAIL); 362 /* set MAC address to emac register */ 363 emac_hal_set_address(&emac->hal, emac->addr); 364 #ifdef CONFIG_PM_ENABLE 365 esp_pm_lock_acquire(emac->pm_lock); 366 #endif 367 return ESP_OK; 368 err: 369 eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL); 370 periph_module_disable(PERIPH_EMAC_MODULE); 371 return ret; 372 } 373 374 static esp_err_t emac_esp32_deinit(esp_eth_mac_t *mac) 375 { 376 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 377 esp_eth_mediator_t *eth = emac->eth; 378 #ifdef CONFIG_PM_ENABLE 379 esp_pm_lock_release(emac->pm_lock); 380 #endif 381 emac_hal_stop(&emac->hal); 382 eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL); 383 periph_module_disable(PERIPH_EMAC_MODULE); 384 return ESP_OK; 385 } 386 387 static esp_err_t emac_esp32_start(esp_eth_mac_t *mac) 388 { 389 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 390 emac_hal_start(&emac->hal); 391 return ESP_OK; 392 } 393 394 static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac) 395 { 396 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 397 emac_hal_stop(&emac->hal); 398 return ESP_OK; 399 } 400 401 static esp_err_t emac_esp32_del(esp_eth_mac_t *mac) 402 { 403 emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent); 404 esp_intr_free(emac->intr_hdl); 405 #ifdef CONFIG_PM_ENABLE 406 if (emac->pm_lock) { 407 esp_pm_lock_delete(emac->pm_lock); 408 } 409 #endif 410 vTaskDelete(emac->rx_task_hdl); 411 int i = 0; 412 for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) { 413 free(emac->hal.rx_buf[i]); 414 } 415 for (i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) { 416 free(emac->hal.tx_buf[i]); 417 } 418 free(emac->hal.descriptors); 419 free(emac); 420 return ESP_OK; 421 } 422 423 // To achieve a better performance, we put the ISR always in IRAM 424 IRAM_ATTR void emac_esp32_isr_handler(void *args) 425 { 426 emac_hal_context_t *hal = (emac_hal_context_t *)args; 427 emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal); 428 emac_hal_isr(args); 429 if (emac->isr_need_yield) { 430 emac->isr_need_yield = false; 431 portYIELD_FROM_ISR(); 432 } 433 } 434 435 esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config) 436 { 437 esp_err_t ret_code = ESP_OK; 438 esp_eth_mac_t *ret = NULL; 439 void *descriptors = NULL; 440 emac_esp32_t *emac = NULL; 441 MAC_CHECK(config, "can't set mac config to null", err, NULL); 442 if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) { 443 emac = heap_caps_calloc(1, sizeof(emac_esp32_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); 444 } else { 445 emac = calloc(1, sizeof(emac_esp32_t)); 446 } 447 MAC_CHECK(emac, "calloc emac failed", err, NULL); 448 /* alloc memory for ethernet dma descriptor */ 449 uint32_t desc_size = CONFIG_ETH_DMA_RX_BUFFER_NUM * sizeof(eth_dma_rx_descriptor_t) + 450 CONFIG_ETH_DMA_TX_BUFFER_NUM * sizeof(eth_dma_tx_descriptor_t); 451 descriptors = heap_caps_calloc(1, desc_size, MALLOC_CAP_DMA); 452 MAC_CHECK(descriptors, "calloc descriptors failed", err, NULL); 453 int i = 0; 454 /* alloc memory for ethernet dma buffer */ 455 for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) { 456 emac->rx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA); 457 if (!(emac->rx_buf[i])) { 458 goto err; 459 } 460 } 461 for (i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) { 462 emac->tx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA); 463 if (!(emac->tx_buf[i])) { 464 goto err; 465 } 466 } 467 /* initialize hal layer driver */ 468 emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf); 469 emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms; 470 emac->smi_mdc_gpio_num = config->smi_mdc_gpio_num; 471 emac->smi_mdio_gpio_num = config->smi_mdio_gpio_num; 472 emac->flow_control_high_water_mark = FLOW_CONTROL_HIGH_WATER_MARK; 473 emac->flow_control_low_water_mark = FLOW_CONTROL_LOW_WATER_MARK; 474 emac->parent.set_mediator = emac_esp32_set_mediator; 475 emac->parent.init = emac_esp32_init; 476 emac->parent.deinit = emac_esp32_deinit; 477 emac->parent.start = emac_esp32_start; 478 emac->parent.stop = emac_esp32_stop; 479 emac->parent.del = emac_esp32_del; 480 emac->parent.write_phy_reg = emac_esp32_write_phy_reg; 481 emac->parent.read_phy_reg = emac_esp32_read_phy_reg; 482 emac->parent.set_addr = emac_esp32_set_addr; 483 emac->parent.get_addr = emac_esp32_get_addr; 484 emac->parent.set_speed = emac_esp32_set_speed; 485 emac->parent.set_duplex = emac_esp32_set_duplex; 486 emac->parent.set_link = emac_esp32_set_link; 487 emac->parent.set_promiscuous = emac_esp32_set_promiscuous; 488 emac->parent.set_peer_pause_ability = emac_esp32_set_peer_pause_ability; 489 emac->parent.enable_flow_ctrl = emac_esp32_enable_flow_ctrl; 490 emac->parent.transmit = emac_esp32_transmit; 491 emac->parent.receive = emac_esp32_receive; 492 /* Interrupt configuration */ 493 if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) { 494 ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM, 495 emac_esp32_isr_handler, &emac->hal, &(emac->intr_hdl)); 496 } else { 497 ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, 498 emac_esp32_isr_handler, &emac->hal, &(emac->intr_hdl)); 499 } 500 MAC_CHECK(ret_code == ESP_OK, "alloc emac interrupt failed", err, NULL); 501 #ifdef CONFIG_PM_ENABLE 502 MAC_CHECK(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "emac_esp32", &emac->pm_lock) == ESP_OK, 503 "create pm lock failed", err, NULL); 504 #endif 505 /* create rx task */ 506 BaseType_t core_num = tskNO_AFFINITY; 507 if (config->flags & ETH_MAC_FLAG_PIN_TO_CORE) { 508 core_num = cpu_hal_get_core_id(); 509 } 510 BaseType_t xReturned = xTaskCreatePinnedToCore(emac_esp32_rx_task, "emac_rx", config->rx_task_stack_size, emac, 511 config->rx_task_prio, &emac->rx_task_hdl, core_num); 512 MAC_CHECK(xReturned == pdPASS, "create emac_rx task failed", err, NULL); 513 return &(emac->parent); 514 515 err: 516 if (emac) { 517 if (emac->rx_task_hdl) { 518 vTaskDelete(emac->rx_task_hdl); 519 } 520 if (emac->intr_hdl) { 521 esp_intr_free(emac->intr_hdl); 522 } 523 for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) { 524 free(emac->tx_buf[i]); 525 } 526 for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) { 527 free(emac->rx_buf[i]); 528 } 529 #ifdef CONFIG_PM_ENABLE 530 if (emac->pm_lock) { 531 esp_pm_lock_delete(emac->pm_lock); 532 } 533 #endif 534 free(emac); 535 } 536 if (descriptors) { 537 free(descriptors); 538 } 539 return ret; 540 } 541 542 IRAM_ATTR void emac_hal_rx_complete_cb(void *arg) 543 { 544 emac_hal_context_t *hal = (emac_hal_context_t *)arg; 545 emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal); 546 BaseType_t high_task_wakeup; 547 /* notify receive task */ 548 vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup); 549 if (high_task_wakeup == pdTRUE) { 550 emac->isr_need_yield = true; 551 } 552 } 553 554 IRAM_ATTR void emac_hal_rx_unavail_cb(void *arg) 555 { 556 emac_hal_context_t *hal = (emac_hal_context_t *)arg; 557 emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal); 558 BaseType_t high_task_wakeup; 559 /* notify receive task */ 560 vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup); 561 if (high_task_wakeup == pdTRUE) { 562 emac->isr_need_yield = true; 563 } 564 } 565 566 IRAM_ATTR void emac_hal_rx_early_cb(void *arg) 567 { 568 emac_hal_context_t *hal = (emac_hal_context_t *)arg; 569 emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal); 570 BaseType_t high_task_wakeup; 571 /* notify receive task */ 572 vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup); 573 if (high_task_wakeup == pdTRUE) { 574 emac->isr_need_yield = true; 575 } 576 }