ch395.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdint.h>
  16. #include "ql_log.h"
  17. #include "ql_api_osi.h"
  18. #include "ql_osi_def.h"
  19. #include "ch395_adapter.h"
  20. #include "CH395CMD.H"
  21. #include "CH395INC.H"
  22. #include "CH395.H"
  23. #define CH395_LOG_LEVEL QL_LOG_LEVEL_INFO
  24. #define CH395_DEMO_LOG(msg, ...) QL_LOG(CH395_LOG_LEVEL, "ch395_log", msg, ##__VA_ARGS__)
  25. #define CH395_ERR_UNKNOW_RETRY_TIME (5 * 1000)
  26. #define CH395_ERR_OPEN_RETRY_TIME (2 * 100)
  27. #define CH395_CONNECTED_CHECK_STATUS_TIME (20 * 1000)
  28. #define CH395_CHECK_STATUS_TIME (10 * 1000)
  29. #define CH395_CHECK_STATUS_RESET_CNT (5)
  30. #define CH395_ERROR_RETRY_TIMES 5
  31. #define CH395_BUFFER_SIZE 1514 //max mac frame len
  32. #define CH395_SOCKET_INDEX 0
  33. typedef struct ch395_list_t
  34. {
  35. struct ch395_list_t *next;
  36. }ch395_list_t;
  37. typedef struct
  38. {
  39. struct ch395_list_t list;
  40. uint8_t *data;
  41. uint32_t len;
  42. }ch395_elem_t;
  43. struct _CH395_SYS
  44. {
  45. UINT8 IPAddr[4]; /* CH395IP地址 32bit*/
  46. UINT8 GWIPAddr[4]; /* CH395网关地址 32bit*/
  47. UINT8 MASKAddr[4]; /* CH395子网掩码 32bit*/
  48. UINT8 MacAddr[6]; /* CH395MAC地址 48bit*/
  49. UINT8 PHYStat; /* CH395 PHY状态码 8bit*/
  50. UINT8 MackFilt; /* CH395 MAC过滤,默认为接收广播,接收本机MAC 8bit*/
  51. UINT32 RetranCount; /* 重试次数 默认为10次*/
  52. UINT32 RetranPeriod; /* 重试周期,单位MS,默认200MS */
  53. UINT8 IntfMode; /* 接口模式 */
  54. UINT8 UnreachIPAddr[4]; /* 不可到达IP */
  55. UINT16 UnreachPort; /* 不可到达端口 */
  56. };
  57. struct _SOCK_INF
  58. {
  59. UINT8 IPAddr[4]; /* socket目标IP地址 32bit*/
  60. UINT8 MacAddr[6]; /* socket目标地址 48bit*/
  61. UINT8 ProtoType; /* 协议类型 */
  62. UINT8 ScokStatus; /* socket状态,参考scoket状态定义 */
  63. UINT8 TcpMode; /* TCP模式 */
  64. UINT32 IPRAWProtoType; /* IPRAW 协议类型 */
  65. UINT16 DesPort; /* 目的端口 */
  66. UINT16 SourPort; /* 目的端口 */
  67. UINT16 SendLen; /* 发送数据长度 */
  68. UINT16 RemLen; /* 剩余长度 */
  69. UINT8 *pSend; /* 发送指针 */
  70. };
  71. typedef struct
  72. {
  73. uint8_t ip4[4];
  74. uint8_t gw[4];
  75. uint8_t netmask[4];
  76. uint8_t mac[6];
  77. ql_ethernet_mode_e mode;
  78. ql_task_t task;
  79. ql_timer_t timer;
  80. uint32_t curr_id;
  81. ch395_app_net_status_e status;
  82. uint8_t status_reset_cnt;
  83. ch395_app_reset_cb_t reset_cb;
  84. ch395_app_notify_cb_t notify_cb;
  85. ql_mutex_t mutex;
  86. }ch395_demo_manager_s;
  87. /* 常用变量定义 */
  88. UINT8 MyBuffer[CH395_BUFFER_SIZE]; /* 数据缓冲区 */
  89. UINT8 SendBuffer[CH395_BUFFER_SIZE];
  90. uint32_t SendBufferLen = 0;
  91. struct _SOCK_INF SockInf; /* 保存Socket信息 */
  92. struct _CH395_SYS CH395Inf; /* 保存CH395信息 */
  93. /* CH395相关定义 */
  94. UINT8 CH395IPAddr[4] = {192,168,1,1}; /* CH395IP地址 */
  95. UINT8 CH395GWIPAddr[4] = {192,168,1,1}; /* CH395网关 */
  96. UINT8 CH395IPMask[4] = {255,255,255,0}; /* CH395子网掩码 */
  97. ch395_demo_manager_s ch395_demo_manager = {0};
  98. bool isConnect = false;
  99. static ql_mutex_t list_lock = NULL;
  100. ch395_list_t list_header;
  101. UINT8 CH395Init(void);
  102. UINT8 CH395SocketInitOpen(void);
  103. /**********************************************************************************
  104. * Function Name :
  105. * Description :
  106. * Input :
  107. * Output :
  108. * Return :
  109. **********************************************************************************/
  110. void ch395_create_mutex(ql_mutex_t* lockaddr)
  111. {
  112. if(!lockaddr)
  113. {
  114. return;
  115. }
  116. if(NULL == *lockaddr)
  117. {
  118. ql_rtos_mutex_create(lockaddr);
  119. }
  120. }
  121. void ch395_delete_mutex(ql_mutex_t lock)
  122. {
  123. if(NULL == lock)
  124. {
  125. return;
  126. }
  127. ql_rtos_mutex_delete(lock);
  128. }
  129. void ch395_try_lock(ql_mutex_t lock)
  130. {
  131. if(NULL == lock)
  132. {
  133. return;
  134. }
  135. ql_rtos_mutex_lock(lock, 0xffffffffUL);
  136. }
  137. void ch395_unlock(ql_mutex_t lock)
  138. {
  139. if(NULL == lock)
  140. {
  141. return;
  142. }
  143. ql_rtos_mutex_unlock(lock);
  144. }
  145. void ch395_list_init(ch395_list_t *header)
  146. {
  147. header->next = NULL;
  148. }
  149. bool ch395_list_add_tail(ch395_list_t *header,uint8_t *data,uint32_t len)
  150. {
  151. //create new node and add it to tail.
  152. ch395_elem_t *elem = (ch395_elem_t *)calloc(1,sizeof(ch395_elem_t));
  153. if(!elem)
  154. {
  155. return false;
  156. }
  157. elem->list.next = NULL;
  158. elem->data = (uint8_t *)calloc(1,len);
  159. if(!(elem->data))
  160. {
  161. return false;
  162. }
  163. memcpy(elem->data,data,len);
  164. elem->len = len;
  165. ch395_list_t *p = header;
  166. while(p->next)
  167. {
  168. p = p->next;
  169. }
  170. p->next = &elem->list;
  171. return true;
  172. };
  173. bool ch395_list_is_empty(ch395_list_t *header)
  174. {
  175. return !(header->next);
  176. }
  177. bool ch395_list_get_head(ch395_list_t *header,uint8_t *data,uint32_t *len)
  178. {
  179. //get and delete the first node
  180. if(ch395_list_is_empty(header))
  181. {
  182. return false;
  183. }
  184. ch395_list_t *p = header;
  185. ch395_elem_t *elem = (ch395_elem_t*)(header->next);
  186. memcpy(data,elem->data,elem->len);
  187. *len = elem->len;
  188. p->next = elem->list.next;
  189. free(elem->data);
  190. free(elem);
  191. return true;
  192. }
  193. void ch395_app_send_event(ql_task_t task,uint32_t id, uint32_t param1, uint32_t param2, uint32_t param3)
  194. {
  195. ql_event_t msg;
  196. msg.id = id;
  197. msg.param1 = param1;
  198. msg.param2 = param2;
  199. msg.param3 = param3;
  200. ql_rtos_event_send(task, &msg);
  201. }
  202. bool ch395_app_check_if_no_err(uint8_t err)
  203. {
  204. if (err == CMD_ERR_SUCCESS) return true; /* 操作成功 */
  205. CH395_DEMO_LOG("CH395 Error: %02X\n", (UINT16)err); /* 显示错误 */
  206. ch395_demo_manager_s* manager = &ch395_demo_manager;
  207. int ret = 0;
  208. switch(err)
  209. {
  210. //硬件错误
  211. default:
  212. case CH395_ERR_UNKNOW:
  213. {
  214. ret = ql_rtos_timer_start(manager->timer, CH395_ERR_UNKNOW_RETRY_TIME, 0);
  215. if (ret != QL_OSI_SUCCESS)
  216. {
  217. CH395_DEMO_LOG("timer start failed");
  218. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_RESET,0,0,0);
  219. }
  220. break;
  221. }
  222. //CH395内部socket错误
  223. case CH395_ERR_OPEN:
  224. {
  225. CH395CloseSocket(CH395_SOCKET_INDEX);
  226. ret = ql_rtos_timer_start(manager->timer, CH395_ERR_OPEN_RETRY_TIME, 0);
  227. if (ret != QL_OSI_SUCCESS)
  228. {
  229. CH395_DEMO_LOG("timer start failed");
  230. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_CONNECT,0,0,0);
  231. }
  232. break;
  233. }
  234. }
  235. return false;
  236. }
  237. /**********************************************************************************
  238. * Function Name : InitCH395InfParam
  239. * Description : 初始化CH395Inf参数
  240. * Input : None
  241. * Output : None
  242. * Return : None
  243. **********************************************************************************/
  244. void InitCH395InfParam(void)
  245. {
  246. ch395_demo_manager_s* manager = &ch395_demo_manager;
  247. memset(&CH395Inf,0,sizeof(CH395Inf)); /* 将CH395Inf全部清零*/
  248. memcpy(CH395Inf.IPAddr,manager->ip4,sizeof(CH395IPAddr)); /* 将IP地址写入CH395Inf中 */
  249. memcpy(CH395Inf.GWIPAddr,manager->gw,sizeof(CH395GWIPAddr)); /* 将网关IP地址写入CH395Inf中 */
  250. memcpy(CH395Inf.MASKAddr,manager->netmask,sizeof(CH395IPMask)); /* 将子网掩码写入CH395Inf中 */
  251. CH395CMDGetMACAddr(CH395Inf.MacAddr);
  252. CH395_DEMO_LOG("CH395EVT:get mac %02x:%02x:%02x:%02x:%02x:%02x",
  253. CH395Inf.MacAddr[0],CH395Inf.MacAddr[1],CH395Inf.MacAddr[2],
  254. CH395Inf.MacAddr[3],CH395Inf.MacAddr[4],CH395Inf.MacAddr[5]);
  255. }
  256. /**********************************************************************************
  257. * Function Name : InitSocketParam
  258. * Description : 初始化socket
  259. * Input : None
  260. * Output : None
  261. * Return : None
  262. **********************************************************************************/
  263. void InitSocketParam(void)
  264. {
  265. memset(&SockInf,0,sizeof(SockInf)); /* 将SockInf[0]全部清零*/
  266. SockInf.ProtoType = PROTO_TYPE_MAC_RAW; /* MAC RAW模式 */
  267. }
  268. /**********************************************************************************
  269. * Function Name : CH395SocketInitOpen
  270. * Description : 配置CH395 socket 参数,初始化并打开socket
  271. * Input : None
  272. * Output : None
  273. * Return : None
  274. **********************************************************************************/
  275. UINT8 CH395SocketInitOpen(void)
  276. {
  277. UINT8 i;
  278. /* socket 0为MAC RAW模式 */
  279. CH395SetSocketProtType(CH395_SOCKET_INDEX,SockInf.ProtoType); /* 设置socket 0协议类型 */
  280. i = CH395OpenSocket(CH395_SOCKET_INDEX); /* 打开socket 0 */
  281. return i;
  282. }
  283. /**********************************************************************************
  284. * Function Name : CH395SocketInterrupt
  285. * Description : CH395 socket 中断,在全局中断中被调用
  286. * Input : sockindex
  287. * Output : None
  288. * Return : None
  289. **********************************************************************************/
  290. void CH395SocketInterrupt(UINT8 sockindex)
  291. {
  292. UINT8 sock_int_socket;
  293. UINT16 len;
  294. ch395_demo_manager_s *manager = &ch395_demo_manager;
  295. sock_int_socket = CH395GetSocketInt(sockindex); /* 获取socket 的中断状态 */
  296. CH395_DEMO_LOG("ch395_sock_int_socket:0x%x",sock_int_socket);
  297. if(sock_int_socket & SINT_STAT_SENBUF_FREE) /* 发送缓冲区空闲,可以继续写入要发送的数据 */
  298. {
  299. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_DATA_OUTPUT,0,0,0);
  300. }
  301. if(sock_int_socket & SINT_STAT_SEND_OK) /* 发送完成中断 */
  302. {
  303. //should be disabled
  304. }
  305. if(sock_int_socket & SINT_STAT_RECV) /* 接收中断 */
  306. {
  307. len = CH395GetRecvLength(sockindex); /* 获取当前缓冲区内数据长度 */
  308. CH395_DEMO_LOG("receive len = %d",len);
  309. if(len == 0)
  310. {
  311. return;
  312. }
  313. if(len > CH395_BUFFER_SIZE)
  314. {
  315. len = CH395_BUFFER_SIZE;
  316. } /*MyBuffer缓冲区长度为1514,*/
  317. CH395GetRecvData(sockindex,len,MyBuffer); /* 读取数据 */
  318. ql_ethernet_data_input(MyBuffer,len);
  319. }
  320. }
  321. /**********************************************************************************
  322. * Function Name : CH395GlobalInterrupt
  323. * Description : CH395全局中断函数
  324. * Input : None
  325. * Output : None
  326. * Return : None
  327. **********************************************************************************/
  328. void CH395GlobalInterrupt(void)
  329. {
  330. UINT16 init_status;
  331. UINT8 buf[10];
  332. ch395_demo_manager_s *manager = &ch395_demo_manager;
  333. init_status = CH395CMDGetGlobIntStatus_ALL();
  334. CH395_DEMO_LOG("ch395_init_status 0x%x",init_status);
  335. if(init_status & GINT_STAT_UNREACH) /* 不可达中断,读取不可达信息 */
  336. {
  337. CH395CMDGetUnreachIPPT(buf);
  338. }
  339. if(init_status & GINT_STAT_IP_CONFLI) /* 产生IP冲突中断,建议重新修改CH395的 IP,并初始化CH395*/
  340. {
  341. }
  342. if(init_status & GINT_STAT_PHY_CHANGE) /* 产生PHY改变中断*/
  343. {
  344. CH395_DEMO_LOG("Init status : GINT_STAT_PHY_CHANGE\n");
  345. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_STATUS_CHECK,0,0,0);
  346. }
  347. if(init_status & GINT_STAT_SOCK0)
  348. {
  349. CH395SocketInterrupt(0); /* 处理socket 0中断*/
  350. }
  351. }
  352. /**********************************************************************************
  353. * Function Name : CH395Init
  354. * Description : 配置CH395的IP,GWIP,MAC等参数,并初始化
  355. * Input : None
  356. * Output : None
  357. * Return : 函数执行结果
  358. **********************************************************************************/
  359. UINT8 CH395Init(void)
  360. {
  361. CH395_DEMO_LOG("CH395init");
  362. UINT8 i;
  363. i = CH395CMDCheckExist(0x65);
  364. if(i != 0x9a)return CH395_ERR_UNKNOW; /* 测试命令,如果无法通过返回0XFA */
  365. /* 返回0XFA一般为硬件错误或者读写时序不对 */
  366. i = CH395CMDInitCH395(); /* 初始化CH395芯片 */
  367. return i;
  368. }
  369. /**********************************************************************************
  370. * Function Name :
  371. * Description :
  372. * Input :
  373. * Output :
  374. * Return :
  375. **********************************************************************************/
  376. void ch395_output(uint8_t * data,uint32_t len)
  377. {
  378. if(len > CH395_BUFFER_SIZE || len == 0)
  379. {
  380. CH395_DEMO_LOG("CH395_drop %d",len);
  381. return;
  382. }
  383. ch395_demo_manager_s *manager = &ch395_demo_manager;
  384. //Put packet to cache.And send it later
  385. ch395_try_lock(list_lock);
  386. bool send = false;
  387. if(ch395_list_is_empty(&list_header))
  388. {
  389. send = true;
  390. }
  391. ch395_list_add_tail(&list_header,data,len);
  392. ch395_unlock(list_lock);
  393. CH395_DEMO_LOG("CH395_output,%d",send);
  394. if(true == send)
  395. {
  396. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_DATA_OUTPUT,0,0,0);
  397. }
  398. }
  399. void _gpioint_cb(void *ctx)
  400. {
  401. ch395_demo_manager_s *manager = &ch395_demo_manager;
  402. //INT# from 1 to 0
  403. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_INT,0,0,0);
  404. CH395_DEMO_LOG("CH395_gpioint_cb");
  405. }
  406. void ch395_app_reset(void)
  407. {
  408. ch395_demo_manager_s* manager = &ch395_demo_manager;
  409. ql_rtos_timer_stop(manager->timer);
  410. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_RESET,0,0,0);
  411. }
  412. ch395_app_gpio_cb_t ch395_app_get_gpio_cb(void)
  413. {
  414. return _gpioint_cb;
  415. }
  416. ch395_app_net_status_e ch395_app_net_status_get()
  417. {
  418. uint8_t status = CH395CMDGetPHYStatus();
  419. uint8_t flag = PHY_DISCONN|PHY_10M_FLL|PHY_10M_HALF|PHY_100M_FLL|PHY_100M_HALF|PHY_AUTO;
  420. CH395_DEMO_LOG("ch395 get status %x",status);
  421. if(status == PHY_DISCONN) /* 查询CH395是否连接 */
  422. {
  423. return CH395_APP_NET_DISCONNECTED;
  424. }
  425. else
  426. {
  427. if(status & (~(flag)) || (status & (status - 1)) != 0)
  428. {
  429. return CH395_APP_NET_NONE;
  430. }
  431. else
  432. {
  433. return CH395_APP_NET_CONNECTED;
  434. }
  435. }
  436. return CH395_APP_NET_NONE;
  437. }
  438. void ch395_app_net_status_notify(ch395_app_net_status_e status)
  439. {
  440. ch395_demo_manager_s* manager = &ch395_demo_manager;
  441. manager->status = status;
  442. if(manager->notify_cb)
  443. {
  444. manager->notify_cb(&status);
  445. }
  446. }
  447. static void ch395_app_timer_cb(void *ctx)
  448. {
  449. ch395_demo_manager_s* manager = &ch395_demo_manager;
  450. CH395_DEMO_LOG("ch395 timer expired,id %x",manager->curr_id);
  451. if(manager->curr_id == QUEC_ETHERNET_DRV_TRY_RESET
  452. || manager->curr_id == QUEC_ETHERNET_DRV_TRY_CONNECT
  453. || manager->curr_id == QUEC_ETHERNET_DRV_STATUS_CHECK)
  454. {
  455. ch395_app_send_event(manager->task,manager->curr_id,0,0,0);
  456. }
  457. return;
  458. }
  459. void ch395_thread(void * arg)
  460. {
  461. ch395_demo_manager_s* manager = &ch395_demo_manager;
  462. ch395_create_mutex(&list_lock);
  463. ch395_create_mutex(&(manager->mutex));
  464. // create timer
  465. int ret = ql_rtos_timer_create(&manager->timer, manager->task, ch395_app_timer_cb, NULL);
  466. if (ret != QL_OSI_SUCCESS)
  467. {
  468. CH395_DEMO_LOG("create timer ret: %x", ret);
  469. goto exit;
  470. }
  471. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_RESET,0,0,0);
  472. CH395_DEMO_LOG("ch395_task");
  473. while(1)
  474. {
  475. ql_event_t event;
  476. if(ql_event_try_wait(&event) != 0)
  477. {
  478. continue;
  479. }
  480. if (event.id == 0)
  481. {
  482. continue;
  483. }
  484. CH395_DEMO_LOG("ch395 read task event:%x",event.id);
  485. switch(event.id)
  486. {
  487. case QUEC_ETHERNET_DRV_TRY_RESET:
  488. {
  489. manager->curr_id = event.id;
  490. if(manager->reset_cb)
  491. {
  492. manager->reset_cb(NULL);
  493. }
  494. uint8_t i = 0;
  495. CH395CMDReset();
  496. ql_rtos_task_sleep_ms(200);
  497. CH395SetStartPara(SOCK_DISABLE_SEND_OK_INT);
  498. i = CH395Init(); /* 初始化CH395芯片 */
  499. if(ch395_app_check_if_no_err(i))
  500. {
  501. CH395_DEMO_LOG("ch395 try connect");
  502. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_CONNECT,0,0,0);
  503. }
  504. ch395_app_net_status_notify(CH395_APP_NET_RESETING);
  505. break;
  506. }
  507. case QUEC_ETHERNET_DRV_TRY_CONNECT:
  508. {
  509. manager->curr_id = event.id;
  510. uint8_t i = 0;
  511. InitCH395InfParam(); /* 初始化CH395相关变量 */
  512. InitSocketParam(); /* 初始化socket相关变量 */
  513. i = CH395SocketInitOpen();
  514. if(ch395_app_check_if_no_err(i))
  515. {
  516. CH395_DEMO_LOG("ch395 check connect status");
  517. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_STATUS_CHECK,0,0,0);
  518. }
  519. ch395_app_net_status_notify(CH395_APP_NET_CONNECTING);
  520. break;
  521. }
  522. case QUEC_ETHERNET_DRV_NET_CREATE:
  523. {
  524. ql_ethernet_errcode_e ret = 0;
  525. ql_ethernet_ctx_s ctx =
  526. {
  527. .ip4 = CH395Inf.IPAddr,
  528. .gw = CH395Inf.GWIPAddr,
  529. .netmask = CH395Inf.MASKAddr,
  530. .mac = CH395Inf.MacAddr,
  531. .mode = manager->mode,
  532. .cb = ch395_output,
  533. };
  534. ret = ql_ethernet_register(&ctx);
  535. CH395_DEMO_LOG("net create %x",ret);
  536. if(QL_ETHERNET_SUCCESS != ret && QL_ETHERNET_REPEAT_REGISTER_ERR != ret)
  537. {
  538. CH395_DEMO_LOG("CH395 register err,try again");
  539. ql_ethernet_deregister();
  540. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_NET_CREATE,0,0,0);
  541. break;
  542. }
  543. else
  544. {
  545. CH395_DEMO_LOG("ch395 connected,net created,from %d to %d",manager->status,CH395_APP_NET_CONNECTED);
  546. ch395_app_net_status_notify(CH395_APP_NET_CONNECTED);
  547. }
  548. break;
  549. }
  550. case QUEC_ETHERNET_DRV_INT:
  551. {
  552. CH395GlobalInterrupt();
  553. break;
  554. }
  555. case QUEC_ETHERNET_DRV_DATA_OUTPUT:
  556. {
  557. //Send one packet to SPI each time.
  558. ch395_try_lock(list_lock);
  559. if(!ch395_list_is_empty(&list_header))
  560. {
  561. ch395_list_get_head(&list_header,SendBuffer,&SendBufferLen);
  562. CH395SendData(CH395_SOCKET_INDEX,(uint8_t*)SendBuffer,SendBufferLen);
  563. CH395_DEMO_LOG("ch395 packet %d sent",SendBufferLen);
  564. }
  565. ch395_unlock(list_lock);
  566. break;
  567. }
  568. case QUEC_ETHERNET_DRV_STATUS_CHECK:
  569. {
  570. manager->curr_id = QUEC_ETHERNET_DRV_STATUS_CHECK;
  571. ch395_app_net_status_e status = ch395_app_net_status_get();
  572. CH395_DEMO_LOG("ch395 status %d",status);
  573. //Error status,try reset after reaching CH395_CHECK_STATUS_RESET_CNT times.
  574. if(status == CH395_APP_NET_NONE)
  575. {
  576. manager->status_reset_cnt++;
  577. if(manager->status_reset_cnt >= CH395_CHECK_STATUS_RESET_CNT)
  578. {
  579. manager->status_reset_cnt = 0;
  580. ql_rtos_timer_stop(manager->timer);
  581. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_TRY_RESET,0,0,0);
  582. CH395_DEMO_LOG("ch395 status read error at %d times,try reset",manager->status_reset_cnt);
  583. }
  584. break;
  585. }
  586. else
  587. {
  588. manager->status_reset_cnt = 0;
  589. }
  590. //Create netcard if net status is from "connecting" to "connected"
  591. if((manager->status == CH395_APP_NET_CONNECTING || manager->status == CH395_APP_NET_DISCONNECTED)
  592. && status == CH395_APP_NET_CONNECTED)
  593. {
  594. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_NET_CREATE,0,0,0);
  595. break;
  596. }
  597. //Keep checking status no matter connected or disconnect
  598. uint32_t check_time = (status == CH395_APP_NET_CONNECTED)?CH395_CONNECTED_CHECK_STATUS_TIME:CH395_CHECK_STATUS_TIME;
  599. CH395_DEMO_LOG("ch395 check time %ds",check_time/1000);
  600. ret = ql_rtos_timer_start(manager->timer, check_time, 0);
  601. if (ret != QL_OSI_SUCCESS)
  602. {
  603. CH395_DEMO_LOG("timer start failed");
  604. ch395_app_send_event(manager->task,QUEC_ETHERNET_DRV_STATUS_CHECK,0,0,0);
  605. }
  606. //Only notify status to upper layer when status changes.
  607. if(manager->status != status)
  608. {
  609. CH395_DEMO_LOG("ch395 status from %d to %d",manager->status,status);
  610. ch395_app_net_status_notify(status);
  611. }
  612. break;
  613. }
  614. default:
  615. {
  616. break;
  617. }
  618. }
  619. }
  620. exit:
  621. ch395_delete_mutex(list_lock);
  622. if(manager->timer)
  623. {
  624. ql_rtos_timer_delete(manager->timer);
  625. }
  626. if(manager->task)
  627. {
  628. ql_rtos_task_delete(manager->task);
  629. }
  630. }
  631. bool ch395_app_cb_register(ch395_app_cb_type_e type,void* cb)
  632. {
  633. if(type >= CH395_APP_CB_TYPE_MAX)
  634. {
  635. return false;
  636. }
  637. ch395_demo_manager_s* manager = &ch395_demo_manager;
  638. switch(type)
  639. {
  640. case CH395_APP_CB_TYPE_RESET:
  641. {
  642. manager->reset_cb = cb;
  643. break;
  644. }
  645. case CH395_APP_CB_TYPE_NOTIFY:
  646. {
  647. manager->notify_cb = cb;
  648. break;
  649. }
  650. default:break;
  651. }
  652. return true;
  653. }
  654. bool ch395_app_init(void* argv)
  655. {
  656. ql_ethernet_ctx_s *ctx = (ql_ethernet_ctx_s*)argv;
  657. bool ret = true;
  658. if(!ctx)
  659. {
  660. CH395_DEMO_LOG("ctx null");
  661. goto exit;
  662. }
  663. ch395_demo_manager_s* manager = &ch395_demo_manager;
  664. if(ctx->ip4)
  665. {
  666. memcpy((void*)(manager->ip4),ctx->ip4,sizeof(manager->ip4));
  667. }
  668. else
  669. {
  670. CH395_DEMO_LOG("ch395 app ip err");
  671. goto exit;
  672. }
  673. if(ctx->gw)
  674. {
  675. memcpy((void*)(manager->gw),ctx->gw,sizeof(manager->gw));
  676. }
  677. else
  678. {
  679. CH395_DEMO_LOG("ch395 app gw err");
  680. goto exit;
  681. }
  682. if(ctx->netmask)
  683. {
  684. memcpy((void*)(manager->netmask),ctx->netmask,sizeof(manager->netmask));
  685. }
  686. else
  687. {
  688. CH395_DEMO_LOG("ch395 app netmask err");
  689. goto exit;
  690. }
  691. if(ctx->mode < QL_ETHERNET_MODE_MAX)
  692. {
  693. manager->mode = ctx->mode;
  694. }
  695. else
  696. {
  697. CH395_DEMO_LOG("ch395 app mode err");
  698. goto exit;
  699. }
  700. QlOSStatus err = QL_OSI_SUCCESS;
  701. err = ql_rtos_task_create(&(manager->task), 8*1024, APP_PRIORITY_REALTIME, "ch395_task", ch395_thread, NULL, 100);
  702. if(err != QL_OSI_SUCCESS)
  703. {
  704. CH395_DEMO_LOG("task created failed");
  705. return false;
  706. }
  707. exit:
  708. return ret;
  709. }
  710. bool ch395_app_deinit(void* argv)
  711. {
  712. ch395_demo_manager_s* manager = &ch395_demo_manager;
  713. ch395_demo_manager_s cmp = {0};
  714. if(0 != memcmp(manager,&cmp,sizeof(ch395_demo_manager_s)))
  715. {
  716. ql_ethernet_deregister();
  717. if(manager->timer)
  718. {
  719. ql_rtos_timer_delete(manager->timer);
  720. }
  721. if(manager->task)
  722. {
  723. ql_rtos_task_delete(manager->task);
  724. manager->task = NULL;
  725. }
  726. memset(manager,0,sizeof(ch395_demo_manager_s));
  727. CH395CMDSleep();
  728. }
  729. else
  730. {
  731. CH395_DEMO_LOG("ch395 already deinit");
  732. }
  733. return true;
  734. }