ethernet_http_demo.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*============================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =============================================================================*/
  5. /*===========================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ---------- ------------ ----------------------------------------------------
  11. =============================================================================*/
  12. /*===========================================================================
  13. * include files
  14. ===========================================================================*/
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include "ql_api_osi.h"
  19. #include "ql_log.h"
  20. #include "ql_gpio.h"
  21. #include "ql_api_spi.h"
  22. #include "ethernet_demo_macro.h"
  23. #include "ql_api_ethernet.h"
  24. #include "ql_api_datacall.h"
  25. #include "ql_api_nw.h"
  26. #include "ql_power.h"
  27. #include "sockets.h"
  28. #include "lwip/ip_addr.h"
  29. #include "lwip/ip6_addr.h"
  30. #include "lwip/inet.h"
  31. #include "lwip/tcp.h"
  32. #ifdef ETHERNET_PHY_CH395
  33. #include "CH395.H"
  34. #endif
  35. /*========================================================================
  36. * Macro Definition
  37. *========================================================================*/
  38. #define QL_ETHERNET_LOG_LEVEL QL_LOG_LEVEL_INFO
  39. #define QL_ETHERNET_DEMO_LOG(msg, ...) QL_LOG(QL_ETHERNET_LOG_LEVEL, "phy_demo", msg, ##__VA_ARGS__)
  40. #ifdef ETHERNET_PHY_CH395
  41. // SPI
  42. #define QL_CUR_SPI_PORT QL_SPI_PORT1
  43. #define QL_CUR_SPI_CS_PIN QL_CUR_SPI1_CS_PIN
  44. #define QL_CUR_SPI_CS_FUNC QL_CUR_SPI1_CS_FUNC
  45. #define QL_CUR_SPI_CLK_PIN QL_CUR_SPI1_CLK_PIN
  46. #define QL_CUR_SPI_CLK_FUNC QL_CUR_SPI1_CLK_FUNC
  47. #define QL_CUR_SPI_DO_PIN QL_CUR_SPI1_DO_PIN
  48. #define QL_CUR_SPI_DO_FUNC QL_CUR_SPI1_DO_FUNC
  49. #define QL_CUR_SPI_DI_PIN QL_CUR_SPI1_DI_PIN
  50. #define QL_CUR_SPI_DI_FUNC QL_CUR_SPI1_DI_FUNC
  51. // GPIO
  52. #define QL_CUR_INT_PIN 59
  53. #define QL_CUR_INT_PIN_GPIO_FUNC 0
  54. #define QL_CUR_INT_GPIO_NUM GPIO_2
  55. #define QL_ETHERNET_HOT_PLUG_PIN 121
  56. #define QL_ETHERNET_HOT_PLUG_PIN_GPIO_FUNC 0
  57. #define QL_ETHERNET_HOT_PLUG_GPIO_NUM GPIO_23
  58. #define QL_ETHERNET_HOT_PLUG_DEBOUNCE_TIME 100
  59. // TCP
  60. #define QL_ETHERNET_PHY_TCP_IP4_SIZE 4
  61. #define QL_ETHERNET_PHY_TCP_CLIENTS_CNT 6
  62. // HTTP
  63. #define QL_ETHERNET_HTTP_ALIGN 8
  64. #define QL_ETHERNET_HTTP_BUFSIZE 8096
  65. #define QL_ETHERNET_HTTP_SEND_BYTES (2 * 1024) // send 2KB each time
  66. #define QL_ETHERNET_HTTP_CONTENT_LEN (10 * 1024 * 1024) // 10MB
  67. #endif
  68. /*========================================================================
  69. * Enumeration Definition
  70. *========================================================================*/
  71. /*========================================================================
  72. * Type Definition
  73. *=========================================================================*/
  74. #ifdef ETHERNET_PHY_CH395
  75. typedef struct
  76. {
  77. int id;
  78. int fd;
  79. uint8_t srcip[QL_ETHERNET_PHY_TCP_IP4_SIZE];
  80. uint16_t srcport;
  81. uint8_t destip[QL_ETHERNET_PHY_TCP_IP4_SIZE];
  82. uint16_t destport;
  83. ql_task_t task;
  84. struct sockaddr_in addr_in;
  85. } ethernet_phy_tcp_ctx_s;
  86. typedef struct
  87. {
  88. ql_spi_port_e port;
  89. ql_LvlMode lvl;
  90. } ethernet_phy_spi_cs_s;
  91. #endif
  92. typedef struct
  93. {
  94. ql_task_t task;
  95. #ifdef ETHERNET_PHY_CH395
  96. ql_mutex_t mutex;
  97. // TCP
  98. ethernet_phy_tcp_ctx_s server_ctx;
  99. ethernet_phy_tcp_ctx_s client_ctx[QL_ETHERNET_PHY_TCP_CLIENTS_CNT];
  100. int client_num;
  101. // Debounce
  102. ql_timer_t timer;
  103. ql_GpioNum gpio_num;
  104. #endif
  105. } ethernet_phy_manager_s;
  106. /*========================================================================
  107. * Global Variable
  108. *========================================================================*/
  109. ethernet_phy_manager_s ethernet_phy_manager = {0};
  110. /*========================================================================
  111. * function Definition
  112. *========================================================================*/
  113. #ifdef ETHERNET_PHY_CH395
  114. void ethernet_phy_create_mutex(ql_mutex_t *lockaddr)
  115. {
  116. if (!lockaddr)
  117. {
  118. return;
  119. }
  120. if (NULL == *lockaddr)
  121. {
  122. ql_rtos_mutex_create(lockaddr);
  123. }
  124. }
  125. void ethernet_phy_delete_mutex(ql_mutex_t lock)
  126. {
  127. if (NULL == lock)
  128. {
  129. return;
  130. }
  131. ql_rtos_mutex_delete(lock);
  132. }
  133. void ethernet_phy_try_lock(ql_mutex_t lock)
  134. {
  135. if (NULL == lock)
  136. {
  137. return;
  138. }
  139. ql_rtos_mutex_lock(lock, 0xffffffffUL);
  140. }
  141. void ethernet_phy_unlock(ql_mutex_t lock)
  142. {
  143. if (NULL == lock)
  144. {
  145. return;
  146. }
  147. ql_rtos_mutex_unlock(lock);
  148. }
  149. void ethernet_phy_send_event(uint32_t id, uint32_t param1, uint32_t param2, uint32_t param3)
  150. {
  151. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  152. ql_event_t event;
  153. event.id = id;
  154. event.param1 = param1;
  155. event.param2 = param2;
  156. event.param3 = param3;
  157. ethernet_phy_try_lock(manager->mutex);
  158. ql_rtos_event_send(manager->task, &event);
  159. ethernet_phy_unlock(manager->mutex);
  160. }
  161. void ethernet_phy_ch395_app_reset_cb(void *ctx)
  162. {
  163. // Do hardware reset here.
  164. QL_ETHERNET_DEMO_LOG("ch395 reset cb");
  165. }
  166. void ethernet_phy_ch395_app_notify_cb(void *ctx)
  167. {
  168. ch395_app_net_status_e status = *((ch395_app_net_status_e *)ctx);
  169. QL_ETHERNET_DEMO_LOG("get phy status: %d", status);
  170. if (status == CH395_APP_NET_CONNECTED)
  171. {
  172. ethernet_phy_send_event(QUEC_ETHERNET_APP_CONNECTED, 0, 0, 0);
  173. }
  174. else if (status == CH395_APP_NET_DISCONNECTED)
  175. {
  176. ethernet_phy_send_event(QUEC_ETHERNET_APP_DISCONNECTED, 0, 0, 0);
  177. }
  178. }
  179. void ethernet_phy_hot_plug_timer_cb(void *ctx)
  180. {
  181. ql_GpioNum gpio_num = *((ql_GpioNum*)ctx);
  182. ql_LvlMode lvl = LVL_LOW;
  183. ql_gpio_get_level(QL_ETHERNET_HOT_PLUG_GPIO_NUM, &lvl);
  184. if(lvl == LVL_LOW)
  185. {
  186. QL_ETHERNET_DEMO_LOG("eth plug in");
  187. ch395_app_reset();
  188. }
  189. else
  190. {
  191. QL_ETHERNET_DEMO_LOG("eth plug out");
  192. }
  193. if(QL_GPIO_SUCCESS !=ql_int_enable(gpio_num))
  194. {
  195. return;
  196. }
  197. }
  198. void ethernet_phy_hot_plug_cb(void *ctx)
  199. {
  200. ql_GpioNum gpio_num = *((ql_GpioNum*)ctx);
  201. if(QL_GPIO_SUCCESS !=ql_int_disable(gpio_num))
  202. {
  203. return;
  204. }
  205. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  206. if(manager->timer == NULL || ql_rtos_timer_is_running(manager->timer))
  207. {
  208. return;
  209. }
  210. QL_ETHERNET_DEMO_LOG("hot plug debounce");
  211. ql_rtos_timer_start(manager->timer, QL_ETHERNET_HOT_PLUG_DEBOUNCE_TIME, 0);
  212. }
  213. int ethernet_phy_int_gpio(void *cb, void *ctx)
  214. {
  215. int err = -1;
  216. // ch395 interrupt
  217. if (QL_GPIO_SUCCESS != ql_pin_set_func(QL_CUR_INT_PIN, QL_CUR_INT_PIN_GPIO_FUNC))
  218. {
  219. goto exit;
  220. }
  221. if (QL_GPIO_SUCCESS != ql_int_register(QL_CUR_INT_GPIO_NUM, EDGE_TRIGGER, DEBOUNCE_DIS, EDGE_FALLING, PULL_UP, cb, ctx))
  222. {
  223. goto exit;
  224. }
  225. if (QL_GPIO_SUCCESS != ql_int_enable(QL_CUR_INT_GPIO_NUM))
  226. {
  227. goto exit;
  228. }
  229. // ch395 hot plug
  230. /*
  231. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  232. manager->gpio_num = QL_ETHERNET_HOT_PLUG_GPIO_NUM;
  233. if (QL_GPIO_SUCCESS != ql_pin_set_func(QL_ETHERNET_HOT_PLUG_PIN, QL_ETHERNET_HOT_PLUG_PIN_GPIO_FUNC))
  234. {
  235. goto exit;
  236. }
  237. if (QL_GPIO_SUCCESS != ql_int_register(QL_ETHERNET_HOT_PLUG_GPIO_NUM, EDGE_TRIGGER, DEBOUNCE_EN, EDGE_BOTH, PULL_UP, ethernet_phy_hot_plug_cb, &(manager->gpio_num)))
  238. {
  239. goto exit;
  240. }
  241. if (QL_GPIO_SUCCESS != ql_int_enable(QL_ETHERNET_HOT_PLUG_GPIO_NUM))
  242. {
  243. goto exit;
  244. }
  245. */
  246. err = 0;
  247. exit:
  248. return err;
  249. }
  250. void ethernet_phy_set_cs(void *ctx)
  251. {
  252. if (!ctx)
  253. {
  254. return;
  255. }
  256. ql_LvlMode lvl = (ql_LvlMode)(*((uint8_t *)ctx));
  257. if (lvl == LVL_HIGH)
  258. {
  259. ql_spi_cs_high(QL_CUR_SPI_PORT);
  260. }
  261. else
  262. {
  263. ql_spi_cs_low(QL_CUR_SPI_PORT);
  264. }
  265. }
  266. static void ethernet_phy_http_error(int nClientScok, int nStatusCode)
  267. {
  268. char str[256] = {0};
  269. int ret = 0;
  270. char *pStrError = "HTTP/1.1 %d NOT FOUND\
  271. Content-Type: text/html\
  272. Accept-Ranges: bytes\
  273. Server: HFS 2.3k\
  274. Set-Cookie: HFS_SID_=0.974440259393305; path=/; HttpOnly\
  275. Content-Encoding: gzip";
  276. QL_ETHERNET_DEMO_LOG("httpd status code:%d", nStatusCode);
  277. ret = snprintf(str, 256, pStrError, nStatusCode);
  278. if (0 != ret)
  279. {
  280. if (ret != write(nClientScok, str, ret))
  281. {
  282. QL_ETHERNET_DEMO_LOG("socket send failed\n");
  283. }
  284. }
  285. }
  286. static void ethernet_phy_http_send(int nClientScok)
  287. {
  288. int ret = 0, len = 0;
  289. int len_temp = 0;
  290. char *buffer_align = NULL;
  291. char *buffer = NULL;
  292. buffer_align = (char *)malloc(QL_ETHERNET_HTTP_ALIGN + QL_ETHERNET_HTTP_BUFSIZE);
  293. if (NULL == buffer_align)
  294. {
  295. ethernet_phy_http_error(nClientScok, 500);
  296. close(nClientScok);
  297. return;
  298. }
  299. buffer = (char *)OSI_ALIGN_UP(buffer_align, QL_ETHERNET_HTTP_ALIGN);
  300. memset(buffer, 0, QL_ETHERNET_HTTP_BUFSIZE + QL_ETHERNET_HTTP_ALIGN);
  301. // read any http streams,no need to parse
  302. struct timeval timeout = {3,0};
  303. setsockopt(nClientScok,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));
  304. ret = read(nClientScok, buffer, QL_ETHERNET_HTTP_BUFSIZE);
  305. if (ret <= 0)
  306. {
  307. ethernet_phy_http_error(nClientScok, 400);
  308. goto exit;
  309. }
  310. else
  311. {
  312. QL_ETHERNET_DEMO_LOG("recv : %s\n", buffer);
  313. }
  314. len = QL_ETHERNET_HTTP_CONTENT_LEN;
  315. snprintf(buffer, QL_ETHERNET_HTTP_BUFSIZE, "HTTP/1.1 200 OK\nServer: Quectel\nContent-Length: %d\nConnection: close\nContent-Type: %s\n\n", len, "application/octet-stream");
  316. // send http header
  317. len_temp = strlen(buffer);
  318. if (len_temp != write(nClientScok, buffer, len_temp))
  319. {
  320. goto exit;
  321. }
  322. // send QL_ETHERNET_HTTP_SEND_BYTES each time
  323. int send_bytes = 0;
  324. int has_sent = 0;
  325. while (has_sent < len)
  326. {
  327. if (has_sent + QL_ETHERNET_HTTP_SEND_BYTES > len)
  328. {
  329. send_bytes = len - QL_ETHERNET_HTTP_SEND_BYTES;
  330. }
  331. else
  332. {
  333. send_bytes = QL_ETHERNET_HTTP_SEND_BYTES;
  334. }
  335. ret = write(nClientScok, buffer, send_bytes);
  336. if (ret < 0)
  337. {
  338. QL_ETHERNET_DEMO_LOG("socket send failed, return %d\n", ret);
  339. break;
  340. }
  341. QL_ETHERNET_DEMO_LOG("phy http send %d/%d/%d", send_bytes, has_sent, len);
  342. has_sent += send_bytes;
  343. }
  344. exit:
  345. close(nClientScok);
  346. free(buffer_align);
  347. return;
  348. }
  349. static void ethernet_phy_client_thread(void *argv)
  350. {
  351. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  352. ethernet_phy_tcp_ctx_s *ctx = (ethernet_phy_tcp_ctx_s *)argv;
  353. QL_ETHERNET_DEMO_LOG("client start:%s:%d", inet_ntoa(ctx->addr_in.sin_addr), ctx->addr_in.sin_port);
  354. // Better use "select" for deleting clients quickly and safely once detecting phy status change.
  355. ethernet_phy_http_send(ctx->fd);
  356. QL_ETHERNET_DEMO_LOG("client end:%s:%d", inet_ntoa(ctx->addr_in.sin_addr), ctx->addr_in.sin_port);
  357. ethernet_phy_try_lock(manager->mutex);
  358. memset(ctx, 0, sizeof(ethernet_phy_tcp_ctx_s));
  359. ctx->id = -1;
  360. ctx->fd = -1;
  361. manager->client_num--;
  362. ethernet_phy_unlock(manager->mutex);
  363. ql_rtos_task_delete(NULL);
  364. }
  365. int ethernet_phy_tcp_client_create(void *argv)
  366. {
  367. if (!argv)
  368. {
  369. QL_ETHERNET_DEMO_LOG("client param err");
  370. return -1;
  371. }
  372. ethernet_phy_tcp_ctx_s *ctx = (ethernet_phy_tcp_ctx_s *)argv;
  373. QlOSStatus err = QL_OSI_SUCCESS;
  374. err = ql_rtos_task_create(&(ctx->task), 4 * 1024, APP_PRIORITY_NORMAL, "phy_client", ethernet_phy_client_thread, argv, 10);
  375. if (err != QL_OSI_SUCCESS)
  376. {
  377. QL_ETHERNET_DEMO_LOG("task created failed");
  378. return -1;
  379. }
  380. return 0;
  381. }
  382. void ethernet_phy_tcp_server(void *argv)
  383. {
  384. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  385. ethernet_phy_tcp_ctx_s *ctx = (ethernet_phy_tcp_ctx_s *)argv;
  386. int socket_fd = -1;
  387. int ret = 0;
  388. struct sockaddr_in local4, client4;
  389. ip4_addr_t int_srcip;
  390. IP4_ADDR(&int_srcip, ctx->srcip[0], ctx->srcip[1], ctx->srcip[2], ctx->srcip[3]);
  391. memset(&local4, 0x00, sizeof(struct sockaddr_in));
  392. local4.sin_family = AF_INET;
  393. local4.sin_port = htons(ctx->srcport);
  394. memcpy(&(local4.sin_addr), &int_srcip, sizeof(int_srcip));
  395. QL_ETHERNET_DEMO_LOG("socket start!");
  396. socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  397. if (socket_fd < 0)
  398. {
  399. goto exit;
  400. }
  401. ret = bind(socket_fd, (struct sockaddr *)&local4, sizeof(struct sockaddr));
  402. if (ret < 0)
  403. {
  404. goto exit;
  405. }
  406. ret = listen(socket_fd, 1);
  407. if (ret < 0)
  408. {
  409. goto exit;
  410. }
  411. ethernet_phy_try_lock(manager->mutex);
  412. ctx->fd = socket_fd;
  413. ethernet_phy_unlock(manager->mutex);
  414. QL_ETHERNET_DEMO_LOG("tcp server wait for clients");
  415. // Better use "select" for deleting server quickly and safely once detecting phy status change.
  416. while (1)
  417. {
  418. int len = sizeof(struct sockaddr);
  419. int con_fd = accept(socket_fd, (struct sockaddr *)&client4, &len);
  420. if (con_fd < 0)
  421. {
  422. QL_ETHERNET_DEMO_LOG("con fd err");
  423. goto exit;
  424. }
  425. ethernet_phy_try_lock(manager->mutex);
  426. //Find NULL task
  427. ethernet_phy_tcp_ctx_s *client_ctx = NULL;
  428. int i = 0;
  429. for (i = 0; i < QL_ETHERNET_PHY_TCP_CLIENTS_CNT; i++)
  430. {
  431. client_ctx = &(manager->client_ctx[i]);
  432. if(NULL == client_ctx->task)
  433. {
  434. break;
  435. }
  436. }
  437. if(i < QL_ETHERNET_PHY_TCP_CLIENTS_CNT)
  438. {
  439. client_ctx->id = i;
  440. client_ctx->fd = con_fd;
  441. memcpy((void *)(&(client_ctx->addr_in)), &client4, sizeof(struct sockaddr));
  442. if (0 == ethernet_phy_tcp_client_create((void *)client_ctx))
  443. {
  444. manager->client_num++;
  445. QL_ETHERNET_DEMO_LOG("client %d", manager->client_num);
  446. }
  447. else
  448. {
  449. QL_ETHERNET_DEMO_LOG("client create failed %d/%d",manager->client_num,QL_ETHERNET_PHY_TCP_CLIENTS_CNT);
  450. }
  451. }
  452. else
  453. {
  454. QL_ETHERNET_DEMO_LOG("client max %d/%d,end", manager->client_num,QL_ETHERNET_PHY_TCP_CLIENTS_CNT);
  455. }
  456. ethernet_phy_unlock(manager->mutex);
  457. }
  458. exit:
  459. QL_ETHERNET_DEMO_LOG("tcp server end");
  460. close(socket_fd);
  461. ethernet_phy_try_lock(manager->mutex);
  462. memset(ctx, 0, sizeof(ethernet_phy_tcp_ctx_s));
  463. ctx->fd = -1;
  464. ethernet_phy_unlock(manager->mutex);
  465. ql_rtos_task_delete(NULL);
  466. return;
  467. }
  468. void ethernet_phy_tcp_server_create(void *argv)
  469. {
  470. if (!argv)
  471. {
  472. QL_ETHERNET_DEMO_LOG("server param err");
  473. return;
  474. }
  475. ethernet_phy_tcp_ctx_s *ctx = (ethernet_phy_tcp_ctx_s *)argv;
  476. if (ctx->task)
  477. {
  478. QL_ETHERNET_DEMO_LOG("server exist");
  479. return;
  480. }
  481. QlOSStatus err = QL_OSI_SUCCESS;
  482. err = ql_rtos_task_create(&(ctx->task), 4 * 1024, APP_PRIORITY_NORMAL, "phy_server", ethernet_phy_tcp_server, argv, 10);
  483. if (err != QL_OSI_SUCCESS)
  484. {
  485. QL_ETHERNET_DEMO_LOG("task created failed");
  486. return;
  487. }
  488. }
  489. #endif
  490. static void ethernet_phy_thread(void *argv)
  491. {
  492. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  493. #ifdef ETHERNET_PHY_CH395
  494. uint8_t srcip[QL_ETHERNET_PHY_TCP_IP4_SIZE] = {192, 168, 1, 100};
  495. uint16_t srcport = 8252; // Zero for random port.
  496. uint8_t gw[QL_ETHERNET_PHY_TCP_IP4_SIZE] = {192, 168, 1, 1};
  497. uint8_t netmask[QL_ETHERNET_PHY_TCP_IP4_SIZE] = {255, 255, 255, 0};
  498. ethernet_phy_create_mutex(&(manager->mutex));
  499. /*
  500. ch395q init
  501. */
  502. ql_ethernet_phy_s spi_ctx =
  503. {
  504. .mode = QL_ETHERNET_PHY_HW_SPI_MODE,
  505. .hw_spi.mosi_pin_num = QL_CUR_SPI_DO_PIN,
  506. .hw_spi.mosi_func_sel = QL_CUR_SPI_DO_FUNC,
  507. .hw_spi.miso_pin_num = QL_CUR_SPI_DI_PIN,
  508. .hw_spi.miso_func_sel = QL_CUR_SPI_DO_FUNC,
  509. .hw_spi.clk_pin_num = QL_CUR_SPI_CLK_PIN,
  510. .hw_spi.clk_func_sel = QL_CUR_SPI_CLK_FUNC,
  511. .hw_spi.cs_pin_num = QL_CUR_SPI_CS_PIN,
  512. .hw_spi.cs_func_sel = QL_CUR_SPI_CS_FUNC,
  513. /*********************************************/
  514. .hw_spi.config.input_mode = QL_SPI_INPUT_TRUE,
  515. .hw_spi.config.port = QL_CUR_SPI_PORT,
  516. .hw_spi.config.spiclk = QL_SPI_CLK_12_5MHZ,
  517. #if QL_SPI_16BIT_DMA
  518. .hw_spi.config.framesize = 16,
  519. #else
  520. .hw_spi.config.framesize = 8,
  521. #endif
  522. .hw_spi.config.cs_polarity0 = QL_SPI_CS_ACTIVE_LOW,
  523. .hw_spi.config.cs_polarity1 = QL_SPI_CS_ACTIVE_LOW,
  524. .hw_spi.config.cpol = QL_SPI_CPOL_LOW,
  525. .hw_spi.config.cpha = QL_SPI_CPHA_1Edge,
  526. .hw_spi.config.input_sel = QL_SPI_DI_1,
  527. .hw_spi.config.transmode = QL_SPI_DMA_IRQ,
  528. .hw_spi.config.cs = QL_SPI_CS0,
  529. .hw_spi.config.clk_delay = QL_SPI_CLK_DELAY_0,
  530. };
  531. if (QL_ETHERNET_SUCCESS != ql_ethernet_phy_init(&spi_ctx))
  532. {
  533. goto exit;
  534. }
  535. if(QL_OSI_SUCCESS != ql_rtos_timer_create(&(manager->timer),manager->task,ethernet_phy_hot_plug_timer_cb,&(manager->gpio_num)))
  536. {
  537. QL_ETHERNET_DEMO_LOG("timer create fail!");
  538. goto exit;
  539. }
  540. if (!ch395_app_cb_register(CH395_APP_CB_TYPE_RESET, ethernet_phy_ch395_app_reset_cb))
  541. {
  542. QL_ETHERNET_DEMO_LOG("ch395 register fail!");
  543. goto exit;
  544. }
  545. if (!ch395_app_cb_register(CH395_APP_CB_TYPE_NOTIFY, ethernet_phy_ch395_app_notify_cb))
  546. {
  547. QL_ETHERNET_DEMO_LOG("ch395 register fail!");
  548. goto exit;
  549. }
  550. if (0 != ethernet_phy_int_gpio(ch395_app_get_gpio_cb(), NULL))
  551. {
  552. goto exit;
  553. }
  554. /*
  555. QUECTEL------------------CH395Q--------------------PC
  556. IP_LAN|192.168.1.100(port) 192.168.1.100(port) 192.168.1.200(8252)
  557. GW |192.168.1.1 192.168.1.1 Any except for 192.168.1.100
  558. */
  559. ql_ethernet_ctx_s ctx =
  560. {
  561. .ip4 = srcip,
  562. .gw = gw,
  563. .netmask = netmask,
  564. .mode = QL_ETHERNET_MODE_NONE,
  565. };
  566. if (!ch395_app_init(&ctx))
  567. {
  568. QL_ETHERNET_DEMO_LOG("ch395 init fail!");
  569. goto exit;
  570. }
  571. while (1)
  572. {
  573. ql_event_t event;
  574. if (ql_event_try_wait(&event) != 0)
  575. {
  576. continue;
  577. }
  578. if (event.id == 0)
  579. {
  580. continue;
  581. }
  582. QL_ETHERNET_DEMO_LOG("ethernet event:%x", event.id);
  583. switch (event.id)
  584. {
  585. case QUEC_ETHERNET_APP_CONNECTED: {
  586. ethernet_phy_tcp_ctx_s *ctx = &(manager->server_ctx);
  587. ethernet_phy_try_lock(manager->mutex);
  588. memcpy(ctx->srcip, srcip, QL_ETHERNET_PHY_TCP_IP4_SIZE);
  589. ctx->srcport = srcport;
  590. ethernet_phy_unlock(manager->mutex);
  591. ethernet_phy_tcp_server_create(ctx);
  592. break;
  593. }
  594. case QUEC_ETHERNET_APP_DISCONNECTED: {
  595. QL_ETHERNET_DEMO_LOG("phy discon");
  596. /*
  597. Server and clients can be set deleting flag here.
  598. Better use "select" for deleting server/clients quickly and safely once detecting phy status change.
  599. */
  600. break;
  601. }
  602. default: {
  603. break;
  604. }
  605. }
  606. }
  607. exit:
  608. QL_ETHERNET_DEMO_LOG("ethernet demo end");
  609. if(manager->timer)
  610. {
  611. ql_rtos_timer_stop(manager->timer);
  612. ql_rtos_timer_delete(manager->timer);
  613. manager->timer = NULL;
  614. }
  615. if (manager->mutex)
  616. {
  617. ql_rtos_mutex_delete(manager->mutex);
  618. manager->mutex = NULL;
  619. }
  620. #endif
  621. if (manager->task)
  622. {
  623. manager->task = NULL;
  624. ql_rtos_task_delete(NULL);
  625. }
  626. }
  627. void ql_ethernet_demo_init(void)
  628. {
  629. ethernet_phy_manager_s *manager = &ethernet_phy_manager;
  630. QlOSStatus err = QL_OSI_SUCCESS;
  631. err = ql_rtos_task_create(&(manager->task), 4 * 1024, APP_PRIORITY_NORMAL, "q_phy_demo", ethernet_phy_thread, NULL, 10);
  632. if (err != QL_OSI_SUCCESS)
  633. {
  634. QL_ETHERNET_DEMO_LOG("task created failed");
  635. return;
  636. }
  637. }