esp_eth_mac_openeth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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. // This is a driver for OpenCores Ethernet MAC (https://opencores.org/projects/ethmac).
  15. // Espressif chips do not use this MAC, but it is supported in QEMU
  16. // (see hw/net/opencores_eth.c). Since the interface of this MAC is a relatively
  17. // simple one, it is used for the purpose of running IDF apps in QEMU.
  18. // The QEMU driver also emulates the DP83848C PHY, which is supported in IDF.
  19. // Note that this driver is written with QEMU in mind. For example, it doesn't
  20. // handle errors which QEMU will not report, and doesn't wait for TX to be
  21. // finished, since QEMU does this instantly.
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <sys/cdefs.h>
  25. #include <sys/param.h>
  26. #include "esp_log.h"
  27. #include "esp_check.h"
  28. #include "esp_eth.h"
  29. #include "esp_intr_alloc.h"
  30. #include "freertos/FreeRTOS.h"
  31. #include "freertos/task.h"
  32. #include "freertos/semphr.h"
  33. #include "hal/cpu_hal.h"
  34. #include "openeth.h"
  35. static const char *TAG = "opencores.emac";
  36. // Driver state structure
  37. typedef struct {
  38. esp_eth_mac_t parent;
  39. esp_eth_mediator_t *eth;
  40. intr_handle_t intr_hdl;
  41. TaskHandle_t rx_task_hdl;
  42. int cur_rx_desc;
  43. int cur_tx_desc;
  44. uint8_t addr[6];
  45. uint8_t *rx_buf[RX_BUF_COUNT];
  46. uint8_t *tx_buf[TX_BUF_COUNT];
  47. } emac_opencores_t;
  48. // Interrupt handler and the receive task
  49. static esp_err_t emac_opencores_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length);
  50. static IRAM_ATTR void emac_opencores_isr_handler(void *args)
  51. {
  52. emac_opencores_t *emac = (emac_opencores_t *) args;
  53. BaseType_t high_task_wakeup;
  54. uint32_t status = REG_READ(OPENETH_INT_SOURCE_REG);
  55. if (status & OPENETH_INT_RXB) {
  56. // Notify receive task
  57. vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
  58. if (high_task_wakeup) {
  59. portYIELD_FROM_ISR();
  60. }
  61. }
  62. if (status & OPENETH_INT_BUSY) {
  63. ESP_EARLY_LOGW(TAG, "%s: RX frame dropped (0x%x)", __func__, status);
  64. }
  65. // Clear interrupt
  66. REG_WRITE(OPENETH_INT_SOURCE_REG, status);
  67. }
  68. static void emac_opencores_rx_task(void *arg)
  69. {
  70. emac_opencores_t *emac = (emac_opencores_t *)arg;
  71. uint8_t *buffer = NULL;
  72. uint32_t length = 0;
  73. while (1) {
  74. if (ulTaskNotifyTake(pdFALSE, portMAX_DELAY)) {
  75. while (true) {
  76. length = ETH_MAX_PACKET_SIZE;
  77. buffer = malloc(length);
  78. if (!buffer) {
  79. ESP_LOGE(TAG, "no mem for receive buffer");
  80. } else if (emac_opencores_receive(&emac->parent, buffer, &length) == ESP_OK) {
  81. // pass the buffer to the upper layer
  82. if (length) {
  83. emac->eth->stack_input(emac->eth, buffer, length);
  84. } else {
  85. free(buffer);
  86. }
  87. } else {
  88. free(buffer);
  89. break;
  90. }
  91. }
  92. }
  93. }
  94. vTaskDelete(NULL);
  95. }
  96. // Below functions implement the driver interface
  97. static esp_err_t emac_opencores_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
  98. {
  99. esp_err_t ret = ESP_OK;
  100. ESP_GOTO_ON_FALSE(eth, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac's mediator to null");
  101. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  102. emac->eth = eth;
  103. return ESP_OK;
  104. err:
  105. return ret;
  106. }
  107. static esp_err_t emac_opencores_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
  108. {
  109. ESP_LOGV(TAG, "%s: addr=%d reg=0x%x val=0x%04x", __func__, phy_addr, phy_reg, reg_value);
  110. REG_SET_FIELD(OPENETH_MIIADDRESS_REG, OPENETH_FIAD, phy_addr);
  111. REG_SET_FIELD(OPENETH_MIIADDRESS_REG, OPENETH_RGAD, phy_reg);
  112. REG_WRITE(OPENETH_MIITX_DATA_REG, reg_value & OPENETH_MII_DATA_MASK);
  113. REG_SET_BIT(OPENETH_MIICOMMAND_REG, OPENETH_WCTRLDATA);
  114. return ESP_OK;
  115. }
  116. static esp_err_t emac_opencores_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
  117. {
  118. esp_err_t ret = ESP_OK;
  119. ESP_GOTO_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, err, TAG, "can't set reg_value to null");
  120. REG_SET_FIELD(OPENETH_MIIADDRESS_REG, OPENETH_FIAD, phy_addr);
  121. REG_SET_FIELD(OPENETH_MIIADDRESS_REG, OPENETH_RGAD, phy_reg);
  122. REG_SET_BIT(OPENETH_MIICOMMAND_REG, OPENETH_RSTAT);
  123. *reg_value = (REG_READ(OPENETH_MIIRX_DATA_REG) & OPENETH_MII_DATA_MASK);
  124. ESP_LOGV(TAG, "%s: addr=%d reg=0x%x val=0x%04x", __func__, phy_addr, phy_reg, *reg_value);
  125. return ESP_OK;
  126. err:
  127. return ret;
  128. }
  129. static esp_err_t emac_opencores_set_addr(esp_eth_mac_t *mac, uint8_t *addr)
  130. {
  131. ESP_LOGV(TAG, "%s: " MACSTR, __func__, MAC2STR(addr));
  132. esp_err_t ret = ESP_OK;
  133. ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
  134. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  135. memcpy(emac->addr, addr, 6);
  136. const uint8_t mac0[4] = {addr[5], addr[4], addr[3], addr[2]};
  137. const uint8_t mac1[4] = {addr[1], addr[0]};
  138. uint32_t mac0_u32, mac1_u32;
  139. memcpy(&mac0_u32, &mac0, 4);
  140. memcpy(&mac1_u32, &mac1, 4);
  141. REG_WRITE(OPENETH_MAC_ADDR0_REG, mac0_u32);
  142. REG_WRITE(OPENETH_MAC_ADDR1_REG, mac1_u32);
  143. return ESP_OK;
  144. err:
  145. return ret;
  146. }
  147. static esp_err_t emac_opencores_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
  148. {
  149. ESP_LOGV(TAG, "%s: " MACSTR, __func__, MAC2STR(addr));
  150. esp_err_t ret = ESP_OK;
  151. ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
  152. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  153. memcpy(addr, emac->addr, 6);
  154. return ESP_OK;
  155. err:
  156. return ret;
  157. }
  158. static esp_err_t emac_opencores_set_link(esp_eth_mac_t *mac, eth_link_t link)
  159. {
  160. ESP_LOGV(TAG, "%s: %s", __func__, link == ETH_LINK_UP ? "up" : "down");
  161. esp_err_t ret = ESP_OK;
  162. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  163. switch (link) {
  164. case ETH_LINK_UP:
  165. ESP_GOTO_ON_ERROR(esp_intr_enable(emac->intr_hdl), err, TAG, "enable interrupt failed");
  166. openeth_enable();
  167. break;
  168. case ETH_LINK_DOWN:
  169. ESP_GOTO_ON_ERROR(esp_intr_disable(emac->intr_hdl), err, TAG, "disable interrupt failed");
  170. openeth_disable();
  171. break;
  172. default:
  173. ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown link status");
  174. break;
  175. }
  176. return ESP_OK;
  177. err:
  178. return ret;
  179. }
  180. static esp_err_t emac_opencores_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
  181. {
  182. /* QEMU doesn't emulate PHY speed, so accept any value */
  183. return ESP_OK;
  184. }
  185. static esp_err_t emac_opencores_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex)
  186. {
  187. /* QEMU doesn't emulate full/half duplex, so accept any value */
  188. return ESP_OK;
  189. }
  190. static esp_err_t emac_opencores_set_promiscuous(esp_eth_mac_t *mac, bool enable)
  191. {
  192. if (enable) {
  193. REG_SET_BIT(OPENETH_MODER_REG, OPENETH_PRO);
  194. } else {
  195. REG_CLR_BIT(OPENETH_MODER_REG, OPENETH_PRO);
  196. }
  197. return ESP_OK;
  198. }
  199. static esp_err_t emac_opencores_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
  200. {
  201. /* QEMU doesn't emulate flow control function, so accept any value */
  202. return ESP_OK;
  203. }
  204. static esp_err_t emac_opencores_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability)
  205. {
  206. /* QEMU doesn't emulate PAUSE function, so accept any value */
  207. return ESP_OK;
  208. }
  209. static esp_err_t emac_opencores_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
  210. {
  211. esp_err_t ret = ESP_OK;
  212. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  213. ESP_GOTO_ON_FALSE(length < DMA_BUF_SIZE * TX_BUF_COUNT, ESP_ERR_INVALID_SIZE, err, TAG, "insufficient TX buffer size");
  214. uint32_t bytes_remaining = length;
  215. // In QEMU, there never is a TX operation in progress, so start with descriptor 0.
  216. ESP_LOGV(TAG, "%s: len=%d", __func__, length);
  217. while (bytes_remaining > 0) {
  218. uint32_t will_write = MIN(bytes_remaining, DMA_BUF_SIZE);
  219. memcpy(emac->tx_buf[emac->cur_tx_desc], buf, will_write);
  220. openeth_tx_desc_t *desc_ptr = openeth_tx_desc(emac->cur_tx_desc);
  221. openeth_tx_desc_t desc_val = *desc_ptr;
  222. desc_val.wr = (emac->cur_tx_desc == TX_BUF_COUNT - 1);
  223. desc_val.len = will_write;
  224. desc_val.rd = 1;
  225. // TXEN is already set, and this triggers a TX operation for the descriptor
  226. ESP_LOGV(TAG, "%s: desc %d (%p) len=%d wr=%d", __func__, emac->cur_tx_desc, desc_ptr, will_write, desc_val.wr);
  227. *desc_ptr = desc_val;
  228. bytes_remaining -= will_write;
  229. buf += will_write;
  230. emac->cur_tx_desc = (emac->cur_tx_desc + 1) % TX_BUF_COUNT;
  231. }
  232. return ESP_OK;
  233. err:
  234. return ret;
  235. }
  236. static esp_err_t emac_opencores_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
  237. {
  238. esp_err_t ret = ESP_OK;
  239. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  240. openeth_rx_desc_t *desc_ptr = openeth_rx_desc(emac->cur_rx_desc);
  241. openeth_rx_desc_t desc_val = *desc_ptr;
  242. ESP_LOGV(TAG, "%s: desc %d (%p) e=%d len=%d wr=%d", __func__, emac->cur_rx_desc, desc_ptr, desc_val.e, desc_val.len, desc_val.wr);
  243. if (desc_val.e) {
  244. ret = ESP_ERR_INVALID_STATE;
  245. goto err;
  246. }
  247. size_t rx_length = desc_val.len;
  248. ESP_GOTO_ON_FALSE(*length >= rx_length, ESP_ERR_INVALID_SIZE, err, TAG, "RX length too large");
  249. *length = rx_length;
  250. memcpy(buf, desc_val.rxpnt, *length);
  251. desc_val.e = 1;
  252. *desc_ptr = desc_val;
  253. emac->cur_rx_desc = (emac->cur_rx_desc + 1) % RX_BUF_COUNT;
  254. return ESP_OK;
  255. err:
  256. return ret;
  257. }
  258. static esp_err_t emac_opencores_init(esp_eth_mac_t *mac)
  259. {
  260. esp_err_t ret = ESP_OK;
  261. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  262. esp_eth_mediator_t *eth = emac->eth;
  263. ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
  264. ESP_GOTO_ON_ERROR(esp_read_mac(emac->addr, ESP_MAC_ETH), err, TAG, "fetch ethernet mac address failed");
  265. // Sanity check
  266. if (REG_READ(OPENETH_MODER_REG) != OPENETH_MODER_DEFAULT) {
  267. ESP_LOGE(TAG, "CONFIG_ETH_USE_OPENETH should only be used when running in QEMU.");
  268. ESP_LOGE(TAG, "When running the app on the ESP32, use CONFIG_ETH_USE_ESP32_EMAC instead.");
  269. abort();
  270. }
  271. // Initialize the MAC
  272. openeth_reset();
  273. openeth_set_tx_desc_cnt(TX_BUF_COUNT);
  274. emac_opencores_set_addr(mac, emac->addr);
  275. return ESP_OK;
  276. err:
  277. eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
  278. return ret;
  279. }
  280. static esp_err_t emac_opencores_deinit(esp_eth_mac_t *mac)
  281. {
  282. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  283. esp_eth_mediator_t *eth = emac->eth;
  284. eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
  285. return ESP_OK;
  286. }
  287. static esp_err_t emac_opencores_start(esp_eth_mac_t *mac)
  288. {
  289. openeth_enable();
  290. return ESP_OK;
  291. }
  292. static esp_err_t emac_opencores_stop(esp_eth_mac_t *mac)
  293. {
  294. openeth_disable();
  295. return ESP_OK;
  296. }
  297. static esp_err_t emac_opencores_del(esp_eth_mac_t *mac)
  298. {
  299. emac_opencores_t *emac = __containerof(mac, emac_opencores_t, parent);
  300. esp_intr_free(emac->intr_hdl);
  301. vTaskDelete(emac->rx_task_hdl);
  302. for (int i = 0; i < RX_BUF_COUNT; i++) {
  303. free(emac->rx_buf[i]);
  304. }
  305. for (int i = 0; i < TX_BUF_COUNT; i++) {
  306. free(emac->tx_buf[i]);
  307. }
  308. free(emac);
  309. return ESP_OK;
  310. }
  311. esp_eth_mac_t *esp_eth_mac_new_openeth(const eth_mac_config_t *config)
  312. {
  313. esp_eth_mac_t *ret = NULL;
  314. emac_opencores_t *emac = NULL;
  315. ESP_GOTO_ON_FALSE(config, NULL, out, TAG, "can't set mac config to null");
  316. emac = calloc(1, sizeof(emac_opencores_t));
  317. ESP_GOTO_ON_FALSE(emac, NULL, out, TAG, "calloc emac failed");
  318. // Allocate DMA buffers
  319. for (int i = 0; i < RX_BUF_COUNT; i++) {
  320. emac->rx_buf[i] = heap_caps_calloc(1, DMA_BUF_SIZE, MALLOC_CAP_DMA);
  321. if (!(emac->rx_buf[i])) {
  322. goto out;
  323. }
  324. openeth_init_rx_desc(openeth_rx_desc(i), emac->rx_buf[i]);
  325. }
  326. openeth_rx_desc(RX_BUF_COUNT - 1)->wr = 1;
  327. emac->cur_rx_desc = 0;
  328. for (int i = 0; i < TX_BUF_COUNT; i++) {
  329. emac->tx_buf[i] = heap_caps_calloc(1, DMA_BUF_SIZE, MALLOC_CAP_DMA);
  330. if (!(emac->tx_buf[i])) {
  331. goto out;
  332. }
  333. openeth_init_tx_desc(openeth_tx_desc(i), emac->tx_buf[i]);
  334. }
  335. openeth_tx_desc(TX_BUF_COUNT - 1)->wr = 1;
  336. emac->cur_tx_desc = 0;
  337. emac->parent.set_mediator = emac_opencores_set_mediator;
  338. emac->parent.init = emac_opencores_init;
  339. emac->parent.deinit = emac_opencores_deinit;
  340. emac->parent.start = emac_opencores_start;
  341. emac->parent.stop = emac_opencores_stop;
  342. emac->parent.del = emac_opencores_del;
  343. emac->parent.write_phy_reg = emac_opencores_write_phy_reg;
  344. emac->parent.read_phy_reg = emac_opencores_read_phy_reg;
  345. emac->parent.set_addr = emac_opencores_set_addr;
  346. emac->parent.get_addr = emac_opencores_get_addr;
  347. emac->parent.set_speed = emac_opencores_set_speed;
  348. emac->parent.set_duplex = emac_opencores_set_duplex;
  349. emac->parent.set_link = emac_opencores_set_link;
  350. emac->parent.set_promiscuous = emac_opencores_set_promiscuous;
  351. emac->parent.set_peer_pause_ability = emac_opencores_set_peer_pause_ability;
  352. emac->parent.enable_flow_ctrl = emac_opencores_enable_flow_ctrl;
  353. emac->parent.transmit = emac_opencores_transmit;
  354. emac->parent.receive = emac_opencores_receive;
  355. // Initialize the interrupt
  356. ESP_GOTO_ON_FALSE(esp_intr_alloc(OPENETH_INTR_SOURCE, ESP_INTR_FLAG_IRAM, emac_opencores_isr_handler, emac, &(emac->intr_hdl)) == ESP_OK, NULL, out, TAG, "alloc emac interrupt failed");
  357. // Create the RX task
  358. BaseType_t core_num = tskNO_AFFINITY;
  359. if (config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
  360. core_num = cpu_hal_get_core_id();
  361. }
  362. BaseType_t xReturned = xTaskCreatePinnedToCore(emac_opencores_rx_task, "emac_rx", config->rx_task_stack_size, emac,
  363. config->rx_task_prio, &emac->rx_task_hdl, core_num);
  364. ESP_GOTO_ON_FALSE(xReturned == pdPASS, NULL, out, TAG, "create emac_rx task failed");
  365. return &(emac->parent);
  366. out:
  367. if (emac) {
  368. if (emac->rx_task_hdl) {
  369. vTaskDelete(emac->rx_task_hdl);
  370. }
  371. if (emac->intr_hdl) {
  372. esp_intr_free(emac->intr_hdl);
  373. }
  374. for (int i = 0; i < TX_BUF_COUNT; i++) {
  375. free(emac->tx_buf[i]);
  376. }
  377. for (int i = 0; i < RX_BUF_COUNT; i++) {
  378. free(emac->rx_buf[i]);
  379. }
  380. free(emac);
  381. }
  382. return ret;
  383. }