ch390h_task.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. #include "luat_base.h"
  2. #include "luat_netdrv.h"
  3. #include "luat_network_adapter.h"
  4. #include "luat_netdrv_ch390h.h"
  5. #include "luat_netdrv_napt.h"
  6. #include "luat_ch390h.h"
  7. #include "luat_malloc.h"
  8. // #include "luat_spi.h"
  9. #include "luat_gpio.h"
  10. #include "net_lwip2.h"
  11. #include "luat_ulwip.h"
  12. #include "lwip/tcp.h"
  13. #include "lwip/sys.h"
  14. #include "lwip/tcpip.h"
  15. #include "lwip/pbuf.h"
  16. #include "luat_mem.h"
  17. #include "luat_mcu.h"
  18. #include "luat_wdt.h"
  19. #include "luat_rtos.h"
  20. #define LUAT_LOG_TAG "netdrv.ch390x"
  21. #include "luat_log.h"
  22. typedef struct pkg_evt
  23. {
  24. uint8_t id;
  25. luat_ch390h_cstring_t* cs;
  26. ch390h_t *ch;
  27. }pkg_evt_t;
  28. // static void print_erp_pkg(uint8_t* buff, uint16_t len);
  29. extern ch390h_t* ch390h_drvs[MAX_CH390H_NUM];
  30. static luat_rtos_task_handle ch390h_task_handle;
  31. static luat_rtos_queue_t qt;
  32. static uint64_t warn_vid_pid_tm;
  33. static uint64_t warn_msg_tm;
  34. static uint32_t s_ch390h_mode; // 0 -- PULL 模式, 1 == IRQ 模式
  35. static int pkg_mem_type = LUAT_HEAP_AUTO;
  36. static int ch390h_irq_cb(void *data, void *args) {
  37. uint32_t len = 0;
  38. luat_rtos_queue_get_cnt(qt, &len);
  39. if (len > 4) {
  40. return 0;
  41. }
  42. pkg_evt_t evt = {
  43. .id = 2
  44. };
  45. luat_rtos_queue_send(qt, &evt, sizeof(pkg_evt_t), 0);
  46. return 0;
  47. }
  48. static int ch390h_bootup(ch390h_t* ch) {
  49. if (ch->ulwip.netif != NULL) {
  50. return 0;
  51. }
  52. // 初始化SPI设备, 由外部代码初始化, 因为不同bsp的速度不一样, 就不走固定值了
  53. luat_gpio_cfg_t gpio_cfg = {0};
  54. // 初始化CS脚
  55. luat_gpio_t gpio = {0};
  56. gpio.pin = ch->cspin;
  57. gpio.mode = LUAT_GPIO_OUTPUT;
  58. gpio.pull = LUAT_GPIO_PULLUP;
  59. gpio.irq = 1;
  60. luat_gpio_setup(&gpio);
  61. // 初始化INT脚
  62. if (ch->intpin != 0xff) {
  63. luat_gpio_set_default_cfg(&gpio_cfg);
  64. gpio_cfg.pin = ch->intpin;
  65. gpio_cfg.mode = LUAT_GPIO_IRQ;
  66. gpio_cfg.irq_type = LUAT_GPIO_RISING_IRQ;
  67. gpio_cfg.pull = 0;
  68. gpio_cfg.irq_cb = ch390h_irq_cb;
  69. luat_gpio_open(&gpio_cfg);
  70. LLOGI("enable irq mode in pin %d", ch->intpin);
  71. s_ch390h_mode = 1;
  72. }
  73. else {
  74. // LLOGI("enable pull mode, use pool mode");
  75. }
  76. // 初始化dhcp相关资源
  77. ch->ulwip.netif = ch->netif;
  78. ch->ulwip.adapter_index = ch->adapter_id;
  79. return 0;
  80. }
  81. static luat_ch390h_cstring_t* new_cstring(uint16_t len) {
  82. size_t total = 0;
  83. size_t used = 0;
  84. size_t max_used = 0;
  85. luat_meminfo_opt_sys(pkg_mem_type, &total, &used, &max_used);
  86. if (total > 0 && total - used > 32*1024) { // 最少留32k给系统用
  87. luat_ch390h_cstring_t* cs = luat_heap_opt_malloc(pkg_mem_type, sizeof(luat_ch390h_cstring_t) + len - 4);
  88. if (cs == NULL) {
  89. LLOGE("有剩余内存不多但分配失败! total %d used %d max_used %d len %d", total, used, max_used, len);
  90. }
  91. return cs;
  92. }
  93. LLOGE("剩余内存不多了,抛弃数据包 total %d used %d max_used %d len %d", total, used, max_used, len);
  94. return NULL;
  95. }
  96. static void send_msg_cs(ch390h_t* ch, luat_ch390h_cstring_t* cs) {
  97. uint32_t len = 0;
  98. luat_rtos_queue_get_cnt(qt, &len);
  99. uint64_t tm;
  100. if (len >= 1000) {
  101. tm = luat_mcu_tick64_ms();
  102. if (tm - warn_msg_tm > 1000) {
  103. warn_msg_tm = tm;
  104. LLOGW("太多待处理消息了!!! %d", len);
  105. }
  106. luat_heap_opt_free(pkg_mem_type, cs);
  107. return;
  108. }
  109. if (len > 512) {
  110. tm = luat_mcu_tick64_ms();
  111. if (tm - warn_msg_tm > 1000) {
  112. warn_msg_tm = tm;
  113. LLOGD("当前消息数量 %d", len);
  114. }
  115. }
  116. pkg_evt_t evt = {
  117. .id = 1,
  118. .cs = cs,
  119. .ch = ch
  120. };
  121. int ret = luat_rtos_queue_send(qt, &evt, sizeof(pkg_evt_t), 0);
  122. if (ret) {
  123. LLOGE("消息发送失败 %d", ret);
  124. luat_heap_opt_free(pkg_mem_type, cs);
  125. }
  126. }
  127. static void ch390h_dataout(luat_netdrv_t* drv, void* userdata, uint8_t* buff, uint16_t len) {
  128. ch390h_t* ch = (ch390h_t*)userdata;
  129. luat_ch390h_cstring_t* cs = new_cstring(len);
  130. if (cs == NULL) {
  131. return;
  132. }
  133. cs->len = len;
  134. memcpy(cs->buff, buff, len);
  135. send_msg_cs(ch, cs);
  136. }
  137. static void ch390h_dataout_pbuf(ch390h_t* ch, struct pbuf* p) {
  138. luat_ch390h_cstring_t* cs = new_cstring(p->tot_len);
  139. if (cs == NULL) {
  140. return;
  141. }
  142. cs->len = p->tot_len;
  143. pbuf_copy_partial(p, cs->buff, p->tot_len, 0);
  144. send_msg_cs(ch, cs);
  145. }
  146. static err_t netif_output(struct netif *netif, struct pbuf *p) {
  147. // LLOGD("lwip待发送数据 %p %d", p, p->tot_len);
  148. ch390h_t* ch = NULL;
  149. for (size_t i = 0; i < MAX_CH390H_NUM; i++)
  150. {
  151. ch = ch390h_drvs[i];
  152. if (ch == NULL) {
  153. continue;
  154. }
  155. if (ch->netif != netif) {
  156. continue;
  157. }
  158. ch390h_dataout_pbuf(ch, p);
  159. break;
  160. }
  161. return 0;
  162. }
  163. static err_t luat_netif_init(struct netif *netif) {
  164. ch390h_t* ch = (ch390h_t*)netif->state;
  165. netif->linkoutput = netif_output;
  166. netif->output = ulwip_etharp_output;
  167. #if ENABLE_PSIF
  168. netif->primary_ipv4_cid = LWIP_PS_INVALID_CID;
  169. #endif
  170. #if LWIP_IPV6
  171. netif->output_ip6 = ethip6_output;
  172. #if ENABLE_PSIF
  173. netif->primary_ipv6_cid = LWIP_PS_INVALID_CID;
  174. #endif
  175. #endif
  176. netif->mtu = 1460;
  177. netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
  178. memcpy(netif->hwaddr, ch->hwaddr, ETH_HWADDR_LEN);
  179. netif->hwaddr_len = ETH_HWADDR_LEN;
  180. net_lwip2_set_netif(ch->adapter_id, ch->netif);
  181. net_lwip2_register_adapter(ch->adapter_id);
  182. netif_set_up(ch->netif);
  183. ch->status++;
  184. LLOGD("luat_netif_init 执行完成 %d", ch->status);
  185. return 0;
  186. }
  187. static void netdrv_netif_input(void* args) {
  188. netdrv_pkg_msg_t* ptr = (netdrv_pkg_msg_t*)args;
  189. struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, ptr->len, PBUF_RAM);
  190. if (p == NULL) {
  191. LLOGD("分配pbuf失败!!! %d", ptr->len);
  192. luat_heap_free(ptr);
  193. return;
  194. }
  195. pbuf_take(p, ptr->buff, ptr->len);
  196. // LLOGD("数据注入到netif " MACFMT, MAC_ARG(p->payload));
  197. int ret = ptr->netif->input(p, ptr->netif);
  198. if (ret) {
  199. pbuf_free(p);
  200. }
  201. luat_heap_free(ptr);
  202. }
  203. static int check_vid_pid(ch390h_t* ch) {
  204. uint8_t buff[6] = {0};
  205. luat_ch390h_read_vid_pid(ch, buff);
  206. if (0 != memcmp(buff, "\x00\x1C\x51\x91", 4)) {
  207. uint64_t tnow = luat_mcu_tick64_ms();
  208. if (tnow - warn_vid_pid_tm > 2000) {
  209. LLOGE("读取vid/pid失败!请检查接线!! %d %d %02X%02X%02X%02X", ch->spiid, ch->cspin, buff[0], buff[1], buff[2], buff[3]);
  210. warn_vid_pid_tm = tnow;
  211. }
  212. return -1;
  213. }
  214. // LLOGE("读取vid/pid成功!!! %d %d %02X%02X%02X%02X", ch->spiid, ch->cspin, buff[0], buff[1], buff[2], buff[3]);
  215. return 0;
  216. }
  217. static int task_loop_one(ch390h_t* ch, luat_ch390h_cstring_t* cs) {
  218. uint8_t buff[32] = {0};
  219. int ret = 0;
  220. uint16_t len = 0;
  221. // LLOGD("状态 spi %d cs %d stat %d", ch->spiid, ch->cspin, ch->status);
  222. // 首先, 判断设备状态
  223. if (ch->status == 0) {
  224. // 状态0, 代表刚加入, 还没成功通信过!!
  225. ch390h_bootup(ch);
  226. luat_ch390h_software_reset(ch);
  227. if (check_vid_pid(ch)) {
  228. return 0;
  229. }
  230. luat_rtos_task_sleep(10);
  231. // 读取MAC地址, 开始初始化
  232. luat_ch390h_read_mac(ch, buff);
  233. for (size_t i = 0; i < 6; i++)
  234. {
  235. if (buff[i] == 0) {
  236. LLOGD("非法MAC地址 %02X%02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  237. return 0;
  238. }
  239. }
  240. luat_ch390h_read_mac(ch, buff + 6);
  241. luat_ch390h_read_mac(ch, buff + 12);
  242. if (memcmp(buff, buff+6, 6) || memcmp(buff, buff+12, 6)) {
  243. LLOGE("读取3次mac地址不匹配!!! %02X%02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  244. return 0;
  245. }
  246. LLOGD("初始化MAC %02X%02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  247. // TODO 判断mac是否合法
  248. memcpy(ch->hwaddr, buff, 6);
  249. netif_add(ch->netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4, ch, luat_netif_init, netif_input);
  250. ch->status++;
  251. ch->netdrv->dataout = ch390h_dataout;
  252. luat_ch390h_basic_config(ch);
  253. luat_ch390h_set_phy(ch, 1);
  254. luat_ch390h_set_rx(ch, 1);
  255. if (ch->intpin != 255) {
  256. luat_ch390h_write_reg(ch, 0x7F, 1); // 开启接收中断
  257. }
  258. return 0; // 等待下一个周期
  259. }
  260. if (check_vid_pid(ch)) {
  261. // TODO 是不是应该恢复到状态0
  262. return 0;
  263. }
  264. if (ch->status == 3) {
  265. LLOGD("request ch390 reset spi%d cs%d", ch->spiid, ch->cspin);
  266. luat_ch390h_software_reset(ch);
  267. ch->status = 2;
  268. luat_rtos_task_sleep(10);
  269. return 0;
  270. }
  271. if (ch->status != 2) {
  272. // 处于中间状态, 暂不管它
  273. LLOGI("wait for netif init %d %d", ch->spiid, ch->cspin);
  274. return 0;
  275. }
  276. // 然后判断link的状态
  277. luat_ch390h_read(ch, 0x01, 1, buff);
  278. uint8_t NSR = buff[0];
  279. // LLOGD("网络状态寄存器 %02X %d", buff[0], (NSR & (1 << 6)) != 0);
  280. if (0 == (NSR & (1 << 6))) {
  281. // 网线没插, 或者phy没有上电
  282. // 首先, 确保phy上电
  283. // luat_ch390h_read(ch, 0x1F, 1, buff);
  284. // LLOGD("PHY状态 %02X", buff[0]);
  285. luat_ch390h_set_phy(ch, 1);
  286. luat_ch390h_set_rx(ch, 1);
  287. if (netif_is_link_up(ch->netif)) {
  288. LLOGI("link is down %d %d", ch->spiid, ch->cspin);
  289. netif_set_link_down(ch->netif);
  290. ulwip_netif_ip_event(&ch->ulwip);
  291. if (ch->dhcp) {
  292. // 停止dhcp定时器
  293. ulwip_dhcp_client_stop(&ch->ulwip);
  294. }
  295. }
  296. return 0; // 网络断了, 没那么快恢复的, 等吧
  297. }
  298. if (!netif_is_link_up(ch->netif)) {
  299. LLOGI("link is up %d %d %s", ch->spiid, ch->cspin, (NSR & (1<<7)) ? "10M" : "100M");
  300. netif_set_link_up(ch->netif);
  301. ulwip_netif_ip_event(&ch->ulwip);
  302. if (ch->dhcp) {
  303. // 启动dhcp定时器
  304. ulwip_dhcp_client_start(&ch->ulwip);
  305. }
  306. }
  307. if (cs) {
  308. // LLOGD("数据写入 %p %d", cs->buff, cs->len);
  309. luat_ch390h_write_pkg(ch, cs->buff, cs->len);
  310. }
  311. // 有没有数据待读取
  312. if (NSR & 0x01) {
  313. ret = luat_ch390h_read_pkg(ch, ch->rxbuff, &len);
  314. if (ret) {
  315. LLOGE("读数据包报错,立即复位模组 ret %d spi %d cs %d", ret, ch->spiid, ch->cspin);
  316. luat_ch390h_write_reg(ch, 0x05, 0);
  317. luat_ch390h_write_reg(ch, 0x55, 1);
  318. luat_ch390h_write_reg(ch, 0x75, 0);
  319. luat_rtos_task_sleep(1); // 是否真的需要呢??
  320. luat_ch390h_basic_config(ch);
  321. luat_ch390h_set_phy(ch, 1);
  322. luat_ch390h_set_rx(ch, 1);
  323. if (ch->intpin != 255) {
  324. luat_ch390h_write_reg(ch, 0x7F, 1); // 开启接收中断
  325. }
  326. return 0;
  327. }
  328. if (len > 0) {
  329. NETDRV_STAT_IN(ch->netdrv, len);
  330. // 收到数据, 开始后续处理
  331. //print_erp_pkg(ch->rxbuff, len);
  332. // 先经过netdrv过滤器
  333. // LLOGD("ETH数据包 " MACFMT " " MACFMT " %02X%02X", MAC_ARG(ch->rxbuff), MAC_ARG(ch->rxbuff + 6), ((uint16_t)ch->rxbuff[6]) + (((uint16_t)ch->rxbuff[7])));
  334. ret = luat_netdrv_napt_pkg_input(ch->adapter_id, ch->rxbuff, len - 4);
  335. // LLOGD("napt ret %d", ret);
  336. if (ret != 0) {
  337. // 不需要输入到LWIP了
  338. // LLOGD("napt说不需要注入lwip了");
  339. }
  340. else {
  341. // 如果返回值是0, 那就是继续处理, 输入到netif
  342. ret = luat_netdrv_netif_input_proxy(ch->netif, ch->rxbuff, len - 4);
  343. if (ret) {
  344. LLOGE("luat_netdrv_netif_input_proxy 返回错误!!! ret %d", ret);
  345. return 1;
  346. }
  347. }
  348. }
  349. // 很好, RX数据处理完成了
  350. }
  351. else {
  352. // LLOGD("没有数据待读取");
  353. }
  354. if (ch->intpin != 255) {
  355. luat_ch390h_write_reg(ch, 0x7E, 0x3F); // 清除中断
  356. }
  357. // 这一轮处理完成了
  358. // 如果rx有数据, 那就不要等待, 立即开始下一轮
  359. if (NSR & 0x01 || cs) {
  360. return 1;
  361. }
  362. return 0;
  363. }
  364. static int task_loop(ch390h_t *ch, luat_ch390h_cstring_t* cs) {
  365. int ret = 0;
  366. for (size_t i = 0; i < MAX_CH390H_NUM; i++)
  367. {
  368. if (ch390h_drvs[i] != NULL && ch390h_drvs[i]->netif != NULL) {
  369. ret += task_loop_one(ch390h_drvs[i], ch == ch390h_drvs[i] ? cs : NULL);
  370. }
  371. }
  372. if (ret) {
  373. luat_rtos_queue_send(qt, &evt, sizeof(pkg_evt_t), 0);
  374. }
  375. return ret;
  376. }
  377. static int task_wait_msg(uint32_t timeout) {
  378. luat_ch390h_cstring_t* cs = NULL;
  379. ch390h_t *ch = NULL;
  380. pkg_evt_t evt = {0};
  381. int ret = luat_rtos_queue_recv(qt, &evt, sizeof(pkg_evt_t), timeout);
  382. // LLOGD("evt id %d ret %d timeout %d", evt.id, ret, timeout);
  383. if (ret == 0 && evt.id == 1) {
  384. // 收到消息了
  385. ch = (ch390h_t *)evt.ch;
  386. cs = (luat_ch390h_cstring_t*)evt.cs;
  387. // LLOGD("收到消息 %p %p", ch, cs);
  388. ret = task_loop(ch, cs);
  389. if (cs) {
  390. // remain_tx_size -= cs->len;
  391. luat_heap_opt_free(pkg_mem_type, cs);
  392. cs = NULL;
  393. }
  394. return 1; // 拿到消息, 那队列里可能还有消息, 马上执行下一轮操作
  395. }
  396. else {
  397. // if (evt.id == 2) {
  398. // LLOGD("CH390中断触发");
  399. // }
  400. ret = task_loop(NULL, NULL);
  401. }
  402. return ret;
  403. }
  404. static void ch390_task_main(void* args) {
  405. (void)args;
  406. int ret = 0;
  407. uint32_t count = 0;
  408. while (1) {
  409. count ++;
  410. if (count % 10 == 0) {
  411. luat_wdt_feed();
  412. }
  413. if (count > 1024) {
  414. if (ret) {
  415. LLOGD("强制休眠20ms");
  416. luat_rtos_task_sleep(20);
  417. }
  418. count = 0;
  419. }
  420. if (s_ch390h_mode == 0) {
  421. ret = task_wait_msg(5);
  422. }
  423. else {
  424. ret = task_wait_msg(1000);
  425. }
  426. }
  427. }
  428. void luat_ch390h_task_start(void) {
  429. int ret = 0;
  430. if (ch390h_task_handle == NULL) {
  431. size_t total = 0;
  432. size_t used = 0;
  433. size_t max_used = 0;
  434. luat_meminfo_opt_sys(LUAT_HEAP_PSRAM, &total, &used, &max_used);
  435. if (total > 1024 * 512) {
  436. pkg_mem_type = LUAT_HEAP_PSRAM;
  437. }
  438. ret = luat_rtos_queue_create(&qt, 1024, sizeof(pkg_evt_t));
  439. if (ret) {
  440. LLOGE("queue create fail %d", ret);
  441. return;
  442. }
  443. ret = luat_rtos_task_create(&ch390h_task_handle, 8*1024, 50, "ch390h", ch390_task_main, NULL, 0);
  444. if (ret) {
  445. LLOGE("task create fail %d", ret);
  446. return;
  447. }
  448. LLOGD("task started");
  449. }
  450. }
  451. // 辅助函数
  452. #if 0
  453. static void print_erp_pkg(uint8_t* buff, uint16_t len) {
  454. // LLOGD("pkg len %d head " MACFMT " " MACFMT, len, MAC_ARG(buff), MAC_ARG(buff+6));
  455. if (len < 24 || len > 1600) {
  456. LLOGW("非法的pkg长度 %d", len);
  457. return;
  458. }
  459. struct eth_hdr* eth = (struct eth_hdr*)buff;
  460. struct ip_hdr* iphdr = (struct ip_hdr*)(buff + SIZEOF_ETH_HDR);
  461. struct etharp_hdr* arp = (struct etharp_hdr*)(buff + SIZEOF_ETH_HDR);
  462. // LLOGD("eth " MACFMT " -> " MACFMT " tp %02X", MAC_ARG(eth->src.addr), MAC_ARG(eth->dest.addr), (u16_t)lwip_htons(eth->type));
  463. switch (eth->type) {
  464. case PP_HTONS(ETHTYPE_IP):
  465. // LLOGD(" ipv%d %d len %d", (u16_t)IPH_V(iphdr), (u16_t)IPH_PROTO(iphdr),(u16_t)IPH_LEN(iphdr));
  466. break;
  467. case PP_HTONS(ETHTYPE_ARP):
  468. // LLOGD(" arp proto %d", arp->proto);
  469. break;
  470. }
  471. }
  472. #endif