emac_main.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. // Copyright 2015-2016 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. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include "rom/ets_sys.h"
  16. #include "rom/gpio.h"
  17. #include "soc/dport_reg.h"
  18. #include "soc/io_mux_reg.h"
  19. #include "soc/rtc_cntl_reg.h"
  20. #include "soc/gpio_reg.h"
  21. #include "soc/dport_reg.h"
  22. #include "soc/emac_ex_reg.h"
  23. #include "soc/emac_reg_v2.h"
  24. #include "soc/soc.h"
  25. #include "tcpip_adapter.h"
  26. #include "sdkconfig.h"
  27. #include "esp_task_wdt.h"
  28. #include "esp_event.h"
  29. #include "esp_system.h"
  30. #include "esp_err.h"
  31. #include "esp_log.h"
  32. #include "esp_eth.h"
  33. #include "esp_intr_alloc.h"
  34. #include "emac_common.h"
  35. #include "emac_desc.h"
  36. #include "freertos/xtensa_api.h"
  37. #include "freertos/FreeRTOS.h"
  38. #include "freertos/task.h"
  39. #include "freertos/queue.h"
  40. #include "freertos/semphr.h"
  41. #include "freertos/timers.h"
  42. #include "lwip/err.h"
  43. #define EMAC_EVT_QNUM 200
  44. #define EMAC_SIG_MAX 50
  45. static struct emac_config_data emac_config;
  46. static uint8_t emac_dma_rx_chain_buf[32 * DMA_RX_BUF_NUM];
  47. static uint8_t emac_dma_tx_chain_buf[32 * DMA_TX_BUF_NUM];
  48. static uint8_t emac_dma_rx_buf[DMA_RX_BUF_SIZE * DMA_RX_BUF_NUM];
  49. static uint8_t emac_dma_tx_buf[DMA_TX_BUF_SIZE * DMA_TX_BUF_NUM];
  50. static SemaphoreHandle_t emac_g_sem;
  51. static portMUX_TYPE g_emac_mux = portMUX_INITIALIZER_UNLOCKED;
  52. static xTaskHandle emac_task_hdl;
  53. static xQueueHandle emac_xqueue;
  54. static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
  55. static TimerHandle_t emac_timer = NULL;
  56. static SemaphoreHandle_t emac_rx_xMutex = NULL;
  57. static SemaphoreHandle_t emac_tx_xMutex = NULL;
  58. static const char *TAG = "emac";
  59. static bool pause_send = false;
  60. static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
  61. esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
  62. static void emac_macaddr_init(void)
  63. {
  64. esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH);
  65. }
  66. void esp_eth_get_mac(uint8_t mac[6])
  67. {
  68. memcpy(mac, &(emac_config.macaddr[0]), 6);
  69. }
  70. static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc , uint32_t size)
  71. {
  72. tx_desc->basic.desc1 = size & 0xfff;
  73. tx_desc->basic.desc0 = EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
  74. tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
  75. }
  76. static void emac_clean_tx_desc(struct dma_extended_desc *tx_desc)
  77. {
  78. tx_desc->basic.desc1 = 0;
  79. tx_desc->basic.desc0 = 0;
  80. }
  81. static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc , uint32_t buf_ptr)
  82. {
  83. if (buf_ptr != 0) {
  84. rx_desc->basic.desc2 = buf_ptr;
  85. }
  86. rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE;
  87. rx_desc->basic.desc0 = EMAC_DESC_RX_OWN;
  88. }
  89. static void emac_set_tx_base_reg(void)
  90. {
  91. REG_WRITE(EMAC_DMATXBASEADDR_REG, (uint32_t)(emac_config.dma_etx));
  92. }
  93. static void emac_set_rx_base_reg(void)
  94. {
  95. REG_WRITE(EMAC_DMARXBASEADDR_REG, (uint32_t)(emac_config.dma_erx));
  96. }
  97. static void emac_reset_dma_chain(void)
  98. {
  99. emac_config.cnt_tx = 0;
  100. emac_config.cur_tx = 0;
  101. emac_config.dirty_tx = 0;
  102. emac_config.cnt_rx = 0;
  103. emac_config.cur_rx = 0;
  104. emac_config.dirty_rx = 0;
  105. }
  106. static void emac_init_dma_chain(void)
  107. {
  108. int i;
  109. uint32_t dma_phy;
  110. struct dma_extended_desc *p = NULL;
  111. //init tx chain
  112. emac_config.dma_etx = (struct dma_extended_desc *)(&emac_dma_tx_chain_buf[0]);
  113. emac_config.cnt_tx = 0;
  114. emac_config.cur_tx = 0;
  115. emac_config.dirty_tx = 0;
  116. dma_phy = (uint32_t)(emac_config.dma_etx);
  117. p = emac_config.dma_etx;
  118. for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++ ) {
  119. dma_phy += sizeof(struct dma_extended_desc);
  120. emac_clean_tx_desc(p);
  121. p->basic.desc3 = dma_phy;
  122. p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
  123. p++;
  124. }
  125. p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
  126. p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
  127. //init desc0 desc1
  128. emac_clean_tx_desc(p);
  129. //init rx chain
  130. emac_config.dma_erx = (struct dma_extended_desc *)(&emac_dma_rx_chain_buf[0]);
  131. emac_config.cnt_rx = 0;
  132. emac_config.cur_rx = 0;
  133. emac_config.dirty_rx = 0;
  134. dma_phy = (uint32_t)(emac_config.dma_erx);
  135. p = emac_config.dma_erx;
  136. for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++ ) {
  137. dma_phy += sizeof(struct dma_extended_desc);
  138. emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
  139. p->basic.desc3 = dma_phy;
  140. p++;
  141. }
  142. emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
  143. p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
  144. }
  145. void esp_eth_smi_write(uint32_t reg_num, uint16_t value)
  146. {
  147. uint32_t phy_num = emac_config.phy_addr;
  148. while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) {
  149. }
  150. REG_WRITE(EMAC_GMACGMIIDATA_REG, value);
  151. REG_WRITE(EMAC_GMACGMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2));
  152. while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) {
  153. }
  154. }
  155. uint16_t esp_eth_smi_read(uint32_t reg_num)
  156. {
  157. uint32_t phy_num = emac_config.phy_addr;
  158. uint16_t value = 0;
  159. while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) {
  160. }
  161. REG_WRITE(EMAC_GMACGMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2));
  162. while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) {
  163. }
  164. value = (REG_READ(EMAC_GMACGMIIDATA_REG) & 0xffff);
  165. return value;
  166. }
  167. esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms)
  168. {
  169. unsigned start = xTaskGetTickCount();
  170. unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
  171. uint16_t current_value = 0;
  172. while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) {
  173. current_value = esp_eth_smi_read(reg_num);
  174. if ((current_value & value_mask) == (value & value_mask)) {
  175. return ESP_OK;
  176. }
  177. vTaskDelay(1);
  178. }
  179. ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x (mask 0x%04x). Current value 0x%04x",
  180. reg_num, value, value_mask, current_value);
  181. return ESP_ERR_TIMEOUT;
  182. }
  183. static void emac_set_user_config_data(eth_config_t *config )
  184. {
  185. emac_config.phy_addr = config->phy_addr;
  186. emac_config.mac_mode = config->mac_mode;
  187. emac_config.phy_init = config->phy_init;
  188. emac_config.emac_tcpip_input = config->tcpip_input;
  189. emac_config.emac_gpio_config = config->gpio_config;
  190. emac_config.emac_phy_check_link = config->phy_check_link;
  191. emac_config.emac_phy_check_init = config->phy_check_init;
  192. emac_config.emac_phy_get_speed_mode = config->phy_get_speed_mode;
  193. emac_config.emac_phy_get_duplex_mode = config->phy_get_duplex_mode;
  194. #if DMA_RX_BUF_NUM > 9
  195. emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable;
  196. #else
  197. if(config->flow_ctrl_enable == true) {
  198. ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run make menuconfig and make sure DMA_RX_BUF_NUM > 9 .");
  199. }
  200. emac_config.emac_flow_ctrl_enable = false;
  201. #endif
  202. emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
  203. emac_config.emac_phy_power_enable = config->phy_power_enable;
  204. }
  205. static void emac_enable_intr()
  206. {
  207. REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
  208. }
  209. static void emac_disable_intr()
  210. {
  211. REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
  212. }
  213. static esp_err_t emac_verify_args(void)
  214. {
  215. esp_err_t ret = ESP_OK;
  216. if (emac_config.phy_addr > PHY31) {
  217. ESP_LOGE(TAG, "phy addr err");
  218. ret = ESP_FAIL;
  219. }
  220. if (emac_config.mac_mode != ETH_MODE_RMII) {
  221. ESP_LOGE(TAG, "mac mode err,now only support RMII");
  222. ret = ESP_FAIL;
  223. }
  224. if (emac_config.phy_init == NULL) {
  225. ESP_LOGE(TAG, "phy_init func is null");
  226. ret = ESP_FAIL;
  227. }
  228. if (emac_config.emac_tcpip_input == NULL) {
  229. ESP_LOGE(TAG, "tcpip_input func is null");
  230. ret = ESP_FAIL;
  231. }
  232. if (emac_config.emac_gpio_config == NULL) {
  233. ESP_LOGE(TAG, "gpio config func is null");
  234. ret = ESP_FAIL;
  235. }
  236. if (emac_config.emac_phy_check_link == NULL) {
  237. ESP_LOGE(TAG, "phy check link func is null");
  238. ret = ESP_FAIL;
  239. }
  240. if (emac_config.emac_phy_check_init == NULL) {
  241. ESP_LOGE(TAG, "phy check init func is null");
  242. ret = ESP_FAIL;
  243. }
  244. if (emac_config.emac_phy_get_speed_mode == NULL) {
  245. ESP_LOGE(TAG, "phy get speed mode func is null");
  246. ret = ESP_FAIL;
  247. }
  248. if (emac_config.emac_phy_get_duplex_mode == NULL) {
  249. ESP_LOGE(TAG, "phy get duplex mode func is null");
  250. ret = ESP_FAIL;
  251. }
  252. if (emac_config.emac_flow_ctrl_enable == true && emac_config.emac_phy_get_partner_pause_enable == NULL) {
  253. ESP_LOGE(TAG, "phy get partner pause enable func is null");
  254. ret = ESP_FAIL;
  255. }
  256. if(emac_config.emac_phy_power_enable == NULL) {
  257. ESP_LOGE(TAG, "phy power enable func is null");
  258. ret = ESP_FAIL;
  259. }
  260. return ret;
  261. }
  262. //TODO for mac filter
  263. void emac_set_mac_addr(void)
  264. {
  265. }
  266. //TODO
  267. void emac_check_mac_addr(void)
  268. {
  269. }
  270. static void emac_process_tx(void)
  271. {
  272. uint32_t cur_tx_desc = emac_read_tx_cur_reg();
  273. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  274. return;
  275. }
  276. xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
  277. while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != cur_tx_desc)) {
  278. emac_clean_tx_desc(&(emac_config.dma_etx[emac_config.dirty_tx]));
  279. emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
  280. emac_config.cnt_tx --;
  281. if (emac_config.cnt_tx < 0) {
  282. ESP_LOGE(TAG, "emac tx chain err");
  283. }
  284. cur_tx_desc = emac_read_tx_cur_reg();
  285. }
  286. xSemaphoreGiveRecursive( emac_tx_xMutex );
  287. }
  288. void esp_eth_free_rx_buf(void *buf)
  289. {
  290. xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
  291. emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.cur_rx]), (uint32_t) buf);
  292. emac_config.cur_rx = (emac_config.cur_rx + 1) % DMA_RX_BUF_NUM;
  293. emac_config.cnt_rx--;
  294. if (emac_config.cnt_rx < 0) {
  295. ESP_LOGE(TAG, "emac rx buf err!!\n");
  296. }
  297. emac_poll_rx_cmd();
  298. xSemaphoreGiveRecursive( emac_rx_xMutex );
  299. if (emac_config.emac_flow_ctrl_partner_support == true) {
  300. portENTER_CRITICAL(&g_emac_mux);
  301. if (pause_send == true && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) {
  302. emac_send_pause_zero_frame_enable();
  303. pause_send = false;
  304. }
  305. portEXIT_CRITICAL(&g_emac_mux);
  306. }
  307. }
  308. static uint32_t IRAM_ATTR emac_get_rxbuf_count_in_intr(void)
  309. {
  310. uint32_t cnt = 0;
  311. uint32_t cur_rx_desc = emac_read_rx_cur_reg();
  312. struct dma_extended_desc *cur_desc = (struct dma_extended_desc *)cur_rx_desc;
  313. while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN) {
  314. cnt++;
  315. cur_desc = (struct dma_extended_desc *)cur_desc->basic.desc3;
  316. }
  317. return cnt;
  318. }
  319. #if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
  320. static void emac_process_rx(void)
  321. {
  322. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  323. return;
  324. }
  325. uint32_t cur_rx_desc = emac_read_rx_cur_reg();
  326. while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
  327. //copy data to lwip
  328. emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
  329. (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
  330. emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
  331. emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
  332. //if open this ,one intr can do many intrs ?
  333. cur_rx_desc = emac_read_rx_cur_reg();
  334. }
  335. emac_enable_rx_intr();
  336. }
  337. static void emac_process_rx_unavail(void)
  338. {
  339. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  340. return;
  341. }
  342. uint32_t dirty_cnt = 0;
  343. while (dirty_cnt < DMA_RX_BUF_NUM) {
  344. if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
  345. break;
  346. }
  347. dirty_cnt ++;
  348. //copy data to lwip
  349. emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
  350. (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
  351. emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
  352. emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
  353. }
  354. emac_enable_rx_intr();
  355. emac_enable_rx_unavail_intr();
  356. emac_poll_rx_cmd();
  357. }
  358. #else
  359. static void emac_process_rx_unavail(void)
  360. {
  361. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  362. return;
  363. }
  364. xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
  365. while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
  366. //copy data to lwip
  367. emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
  368. (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
  369. emac_config.cnt_rx++;
  370. if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
  371. ESP_LOGE(TAG, "emac rx unavail buf err !!\n");
  372. }
  373. emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
  374. }
  375. emac_enable_rx_intr();
  376. emac_enable_rx_unavail_intr();
  377. xSemaphoreGiveRecursive( emac_rx_xMutex );
  378. }
  379. static void emac_process_rx(void)
  380. {
  381. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  382. return;
  383. }
  384. uint32_t cur_rx_desc = emac_read_rx_cur_reg();
  385. xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
  386. if (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
  387. while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
  388. //copy data to lwip
  389. emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
  390. (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
  391. emac_config.cnt_rx++;
  392. if (emac_config.cnt_rx > DMA_RX_BUF_NUM ) {
  393. ESP_LOGE(TAG, "emac rx buf err!!\n");
  394. }
  395. emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
  396. cur_rx_desc = emac_read_rx_cur_reg();
  397. }
  398. } else {
  399. if (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
  400. if ((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) == 0) {
  401. while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
  402. //copy data to lwip
  403. emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
  404. (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
  405. emac_config.cnt_rx++;
  406. if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
  407. ESP_LOGE(TAG, "emac rx buf err!!!\n");
  408. }
  409. emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
  410. }
  411. }
  412. }
  413. }
  414. emac_enable_rx_intr();
  415. xSemaphoreGiveRecursive( emac_rx_xMutex );
  416. }
  417. #endif
  418. //TODO other events need to do something
  419. static void IRAM_ATTR emac_process_intr(void *arg)
  420. {
  421. uint32_t event;
  422. event = REG_READ(EMAC_DMASTATUS_REG);
  423. //clr intrs
  424. REG_WRITE(EMAC_DMASTATUS_REG, event);
  425. if (event & EMAC_RECV_INT) {
  426. emac_disable_rx_intr();
  427. if (emac_config.emac_flow_ctrl_partner_support == true) {
  428. if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && pause_send == false ) {
  429. pause_send = true;
  430. emac_send_pause_frame_enable();
  431. }
  432. }
  433. emac_post(SIG_EMAC_RX_DONE, 0);
  434. }
  435. if (event & EMAC_RECV_BUF_UNAVAIL) {
  436. emac_disable_rx_unavail_intr();
  437. emac_post(SIG_EMAC_RX_UNAVAIL, 0);
  438. }
  439. if (event & EMAC_TRANS_INT) {
  440. emac_post(SIG_EMAC_TX_DONE, 0);
  441. }
  442. }
  443. static void emac_set_macaddr_reg(void)
  444. {
  445. REG_SET_FIELD(EMAC_GMACADDR0HIGH_REG, EMAC_MAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1]));
  446. REG_WRITE(EMAC_GMACADDR0LOW_REG, (emac_config.macaddr[2] << 24) | (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5]));
  447. }
  448. static void emac_check_phy_init(void)
  449. {
  450. emac_config.emac_phy_check_init();
  451. if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
  452. REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
  453. } else {
  454. REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
  455. }
  456. if (emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
  457. REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
  458. } else {
  459. REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
  460. }
  461. #if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
  462. emac_disable_flowctrl();
  463. emac_config.emac_flow_ctrl_partner_support = false;
  464. #else
  465. if (emac_config.emac_flow_ctrl_enable == true) {
  466. if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
  467. emac_enable_flowctrl();
  468. emac_config.emac_flow_ctrl_partner_support = true;
  469. } else {
  470. emac_disable_flowctrl();
  471. emac_config.emac_flow_ctrl_partner_support = false;
  472. }
  473. } else {
  474. emac_disable_flowctrl();
  475. emac_config.emac_flow_ctrl_partner_support = false;
  476. }
  477. #endif
  478. emac_mac_enable_txrx();
  479. }
  480. static void emac_process_link_updown(bool link_status)
  481. {
  482. system_event_t evt;
  483. uint8_t i = 0;
  484. emac_config.phy_link_up = link_status;
  485. if (link_status == true) {
  486. emac_check_phy_init();
  487. ESP_LOGI(TAG, "eth link_up!!!");
  488. emac_enable_dma_tx();
  489. emac_enable_dma_rx();
  490. for (i = 0; i < PHY_LINK_CHECK_NUM; i++) {
  491. emac_check_phy_init();
  492. }
  493. evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
  494. } else {
  495. ESP_LOGI(TAG, "eth link_down!!!");
  496. emac_disable_dma_tx();
  497. emac_disable_dma_rx();
  498. evt.event_id = SYSTEM_EVENT_ETH_DISCONNECTED;
  499. }
  500. esp_event_send(&evt);
  501. }
  502. static void emac_hw_init(void)
  503. {
  504. //init chain
  505. emac_init_dma_chain();
  506. //get hw features TODO
  507. //ipc TODO
  508. }
  509. esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
  510. {
  511. esp_err_t ret = ESP_OK;
  512. if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
  513. ESP_LOGI(TAG, "tx netif close");
  514. ret = ERR_IF;
  515. return ret;
  516. }
  517. xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
  518. if (emac_config.cnt_tx == DMA_TX_BUF_NUM - 1) {
  519. ESP_LOGD(TAG, "tx buf full");
  520. ret = ERR_MEM;
  521. goto _exit;
  522. }
  523. memcpy((uint8_t *)(emac_config.dma_etx[emac_config.cur_tx].basic.desc2), (uint8_t *)buf, size);
  524. emac_setup_tx_desc(&(emac_config.dma_etx[emac_config.cur_tx]), size);
  525. emac_config.cnt_tx ++;
  526. emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM ;
  527. emac_poll_tx_cmd();
  528. _exit:
  529. xSemaphoreGiveRecursive( emac_tx_xMutex );
  530. return ret;
  531. }
  532. static void emac_init_default_data(void)
  533. {
  534. memset((uint8_t *)&emac_config, 0, sizeof(struct emac_config_data));
  535. }
  536. void emac_process_link_check(void)
  537. {
  538. if (emac_config.emac_status != EMAC_RUNTIME_START ||
  539. emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
  540. return;
  541. }
  542. if (emac_config.emac_phy_check_link() == true ) {
  543. if (emac_config.phy_link_up == false) {
  544. emac_process_link_updown(true);
  545. }
  546. } else {
  547. if (emac_config.phy_link_up == true) {
  548. emac_process_link_updown(false);
  549. }
  550. }
  551. }
  552. void emac_link_check_func(void *pv_parameters)
  553. {
  554. emac_post(SIG_EMAC_CHECK_LINK, 0);
  555. }
  556. static bool emac_link_check_timer_init(void)
  557. {
  558. emac_timer = xTimerCreate("emac_timer", (2000 / portTICK_PERIOD_MS),
  559. pdTRUE, (void *)rand(), emac_link_check_func);
  560. if (emac_timer == NULL) {
  561. return false;
  562. } else {
  563. return true;
  564. }
  565. }
  566. static bool emac_link_check_timer_start(void)
  567. {
  568. if (xTimerStart(emac_timer, portMAX_DELAY) != pdPASS) {
  569. return false;
  570. } else {
  571. return true;
  572. }
  573. }
  574. static bool emac_link_check_timer_stop(void)
  575. {
  576. if (xTimerStop(emac_timer, portMAX_DELAY) != pdPASS) {
  577. return false;
  578. } else {
  579. return true;
  580. }
  581. }
  582. static bool emac_link_check_timer_delete(void)
  583. {
  584. xTimerDelete(emac_timer, portMAX_DELAY);
  585. emac_timer = NULL;
  586. return true;
  587. }
  588. static void emac_start(void *param)
  589. {
  590. struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
  591. struct emac_open_cmd *cmd = (struct emac_open_cmd *)(post_cmd->cmd);
  592. ESP_LOGI(TAG , "emac start !!!\n");
  593. cmd->err = EMAC_CMD_OK;
  594. emac_enable_clk(true);
  595. emac_reset();
  596. emac_macaddr_init();
  597. emac_check_mac_addr();
  598. emac_set_mac_addr();
  599. emac_set_macaddr_reg();
  600. emac_set_tx_base_reg();
  601. emac_set_rx_base_reg();
  602. emac_mac_init();
  603. emac_config.phy_init();
  604. //ptp TODO
  605. emac_enable_intr();
  606. emac_config.emac_status = EMAC_RUNTIME_START;
  607. system_event_t evt;
  608. evt.event_id = SYSTEM_EVENT_ETH_START;
  609. esp_event_send(&evt);
  610. //set a timer to check link up status
  611. if (emac_link_check_timer_init() == true) {
  612. if (emac_link_check_timer_start() != true) {
  613. cmd->err = EMAC_CMD_FAIL;
  614. emac_link_check_timer_delete();
  615. }
  616. } else {
  617. cmd->err = EMAC_CMD_FAIL;
  618. }
  619. if (post_cmd->post_type == EMAC_POST_SYNC) {
  620. xSemaphoreGive(emac_g_sem);
  621. }
  622. ESP_LOGI(TAG, "emac start success !!!");
  623. }
  624. esp_err_t esp_eth_enable(void)
  625. {
  626. struct emac_post_cmd post_cmd;
  627. struct emac_open_cmd open_cmd;
  628. post_cmd.cmd = (void *)(&open_cmd);
  629. open_cmd.err = EMAC_CMD_OK;
  630. if (emac_config.emac_status == EMAC_RUNTIME_START) {
  631. open_cmd.err = EMAC_CMD_OK;
  632. return open_cmd.err;
  633. }
  634. if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
  635. if (emac_ioctl(SIG_EMAC_START, (emac_par_t)(&post_cmd)) != 0) {
  636. open_cmd.err = EMAC_CMD_FAIL;
  637. }
  638. } else {
  639. open_cmd.err = EMAC_CMD_FAIL;
  640. }
  641. return open_cmd.err;
  642. }
  643. static void emac_stop(void *param)
  644. {
  645. struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
  646. ESP_LOGI(TAG, "emac stop");
  647. emac_link_check_timer_stop();
  648. emac_link_check_timer_delete();
  649. emac_process_link_updown(false);
  650. emac_disable_intr();
  651. emac_reset_dma_chain();
  652. emac_reset();
  653. emac_enable_clk(false);
  654. emac_config.emac_status = EMAC_RUNTIME_STOP;
  655. system_event_t evt;
  656. evt.event_id = SYSTEM_EVENT_ETH_STOP;
  657. esp_event_send(&evt);
  658. if (post_cmd->post_type == EMAC_POST_SYNC) {
  659. xSemaphoreGive(emac_g_sem);
  660. }
  661. ESP_LOGI(TAG, "emac stop success !!!");
  662. }
  663. esp_err_t esp_eth_disable(void)
  664. {
  665. struct emac_post_cmd post_cmd;
  666. struct emac_close_cmd close_cmd;
  667. post_cmd.cmd = (void *)(&close_cmd);
  668. close_cmd.err = EMAC_CMD_OK;
  669. if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
  670. close_cmd.err = EMAC_CMD_OK;
  671. return close_cmd.err;
  672. }
  673. if (emac_config.emac_status == EMAC_RUNTIME_START) {
  674. if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) {
  675. close_cmd.err = EMAC_CMD_FAIL;
  676. }
  677. } else {
  678. close_cmd.err = EMAC_CMD_FAIL;
  679. }
  680. return close_cmd.err;
  681. }
  682. static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
  683. {
  684. esp_err_t ret = ESP_OK;
  685. struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)par;
  686. xTaskHandle task_hdl = xTaskGetCurrentTaskHandle();
  687. if (emac_task_hdl != task_hdl) {
  688. post_cmd->post_type = EMAC_POST_SYNC;
  689. if (emac_post(sig, par) != ESP_OK) {
  690. ret = ESP_FAIL;
  691. return ret;
  692. };
  693. if (xSemaphoreTake(emac_g_sem, portMAX_DELAY) == pdTRUE) {
  694. return ret;
  695. }
  696. } else {
  697. post_cmd->post_type = EMAC_POST_ASYNC;
  698. switch (sig) {
  699. case SIG_EMAC_RX_DONE:
  700. emac_process_rx();
  701. break;
  702. case SIG_EMAC_TX_DONE:
  703. emac_process_tx();
  704. break;
  705. case SIG_EMAC_START:
  706. emac_start((void *)par);
  707. break;
  708. case SIG_EMAC_STOP:
  709. emac_stop((void *)par);
  710. break;
  711. default:
  712. ESP_LOGE(TAG, "unexpect sig %d", sig);
  713. break;
  714. }
  715. }
  716. return ret;
  717. }
  718. void emac_task(void *pv)
  719. {
  720. emac_event_t e;
  721. for (;;) {
  722. if (xQueueReceive(emac_xqueue, &e, (portTickType)portMAX_DELAY) == pdTRUE) {
  723. portENTER_CRITICAL(&g_emac_mux);
  724. emac_sig_cnt[e.sig]--;
  725. portEXIT_CRITICAL(&g_emac_mux);
  726. switch (e.sig) {
  727. case SIG_EMAC_RX_DONE:
  728. emac_process_rx();
  729. break;
  730. case SIG_EMAC_RX_UNAVAIL:
  731. emac_process_rx_unavail();
  732. break;
  733. case SIG_EMAC_TX_DONE:
  734. emac_process_tx();
  735. break;
  736. case SIG_EMAC_START:
  737. emac_start((void *)e.par);
  738. break;
  739. case SIG_EMAC_STOP:
  740. emac_stop((void *)e.par);
  741. break;
  742. case SIG_EMAC_CHECK_LINK:
  743. emac_process_link_check();
  744. break;
  745. default:
  746. ESP_LOGE(TAG, "unexpect sig %d", e.sig);
  747. break;
  748. }
  749. }
  750. }
  751. }
  752. esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
  753. {
  754. if (sig <= SIG_EMAC_RX_DONE) {
  755. if (emac_sig_cnt[sig]) {
  756. return ESP_OK;
  757. } else {
  758. emac_sig_cnt[sig]++;
  759. emac_event_t evt;
  760. signed portBASE_TYPE ret;
  761. evt.sig = sig;
  762. evt.par = par;
  763. portBASE_TYPE tmp;
  764. ret = xQueueSendFromISR(emac_xqueue, &evt, &tmp);
  765. if (tmp != pdFALSE) {
  766. portYIELD_FROM_ISR();
  767. }
  768. if (ret != pdPASS) {
  769. return ESP_FAIL;
  770. }
  771. }
  772. } else {
  773. portENTER_CRITICAL(&g_emac_mux);
  774. emac_sig_cnt[sig]++;
  775. portEXIT_CRITICAL(&g_emac_mux);
  776. emac_event_t evt;
  777. evt.sig = sig;
  778. evt.par = par;
  779. if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
  780. return ESP_FAIL;
  781. }
  782. }
  783. return ESP_OK;
  784. }
  785. esp_err_t esp_eth_init(eth_config_t *config)
  786. {
  787. esp_err_t ret = ESP_OK;
  788. #if !CONFIG_ETHERNET
  789. ESP_LOGI(TAG, "eth driver init fail,please make menuconfig and enable ethernet .");
  790. ret = ESP_FAIL;
  791. goto _exit;
  792. #endif
  793. emac_init_default_data();
  794. if (config != NULL ) {
  795. emac_set_user_config_data(config);
  796. }
  797. ret = emac_verify_args();
  798. if (ret != ESP_OK) {
  799. goto _exit;
  800. }
  801. emac_config.emac_phy_power_enable(true);
  802. //before set emac reg must enable clk
  803. emac_enable_clk(true);
  804. REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII);
  805. emac_dma_init();
  806. if (emac_config.mac_mode == ETH_MODE_RMII) {
  807. emac_set_clk_rmii();
  808. } else {
  809. emac_set_clk_mii();
  810. }
  811. emac_config.emac_gpio_config();
  812. ESP_LOGI(TAG, "mac version %04xa", emac_read_mac_version());
  813. emac_hw_init();
  814. //watchdog TODO
  815. //init task for emac
  816. emac_g_sem = xSemaphoreCreateBinary();
  817. emac_rx_xMutex = xSemaphoreCreateRecursiveMutex();
  818. emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
  819. emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
  820. xTaskCreate(emac_task, "emacT", 2048, NULL, EMAC_TASK_PRIORITY, &emac_task_hdl);
  821. emac_enable_clk(false);
  822. esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
  823. emac_config.emac_status = EMAC_RUNTIME_INIT;
  824. _exit:
  825. return ret;
  826. }