can_app.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: can_app.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2013-02-28
  7. 功能说明: can传输应用层
  8. 其它说明:
  9. 修改记录:
  10. */
  11. /*------------------------------- 头文件 --------------------------------------
  12. */
  13. #include "head.h"
  14. #ifdef BSP_CAN_ENABLE
  15. /*------------------------------- 宏定义 --------------------------------------
  16. */
  17. /*------------------------------ 类型结构 -------------------------------------
  18. */
  19. /*------------------------------ 全局变量 -------------------------------------
  20. */
  21. int g_sb_monitor;
  22. /*------------------------------ 函数声明 -------------------------------------
  23. */
  24. int can_app_callback(u32 can_bus, u8 *buf);
  25. /*------------------------------ 外部函数 -------------------------------------
  26. 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
  27. */
  28. int can_app_init(void)
  29. {
  30. can_regester_recv_callback(can_app_callback);
  31. return 0;
  32. }
  33. int can_app_exit(void)
  34. {
  35. can_regester_recv_callback(NULL);
  36. return 0;
  37. }
  38. int can_app_callback(u32 can_bus, u8 *buf)
  39. {
  40. struct can_frame_head *cfh;
  41. // 检查参数
  42. if (can_bus >= CAN_BUS_NUM)
  43. {
  44. return -1;
  45. }
  46. if (buf == NULL)
  47. {
  48. return -2;
  49. }
  50. cfh = (struct can_frame_head *)buf;
  51. switch (cfh->type)
  52. {
  53. case CAN_FRAME_TYPE_DI_INIT:
  54. case CAN_FRAME_TYPE_DI_ON:
  55. case CAN_FRAME_TYPE_DI_OFF:
  56. case CAN_FRAME_TYPE_DI_INIT1:
  57. case CAN_FRAME_TYPE_DI_ON1:
  58. case CAN_FRAME_TYPE_DI_OFF1:
  59. dido_di_update(buf);
  60. break;
  61. case CAN_FRAME_TYPE_SB_INFO:
  62. #if defined(CAN_SLAVE_BOARD)
  63. equ_board_info_update(can_bus, buf);
  64. #endif
  65. break;
  66. default:
  67. return 0;
  68. break;
  69. }
  70. return 1;
  71. }
  72. u8 can_app_checksum(u8 *buf, u8 len)
  73. {
  74. u8 i, sum;
  75. sum = 0;
  76. for (i = 0; i < len; i++)
  77. {
  78. sum += *buf++;
  79. }
  80. return sum;
  81. }
  82. int can_app_timing(void)
  83. {
  84. static long g_timing_sec = 0;
  85. int i, ret;
  86. u8 *buf;
  87. struct timespec ts;
  88. clk_time_get(&ts);
  89. // 对时帧必须在内部对时秒脉冲发出10ms后再发送,每秒发送一次。
  90. if (ts.tv_sec == g_timing_sec || ts.tv_nsec < 10 * NSEC_PER_MS)
  91. {
  92. return 0;
  93. }
  94. // 帧头
  95. buf = can_request_tx_buf(CAN_FRAME_TYPE_TIMING);
  96. buf[0] = CAN_FRAME_TYPE_TIMING;
  97. buf[1] = CAN_BUS_ADDR_BCAST;
  98. buf[2] = 0;
  99. buf[3] = sizeof(int); // long -> int 8byte -> 4 byte, 暂时按回4字节传输,待确认 EWen
  100. // 得到时间
  101. memcpy(buf + 4, &ts.tv_sec, sizeof(int)); // noted by sunxi: 这里需要注意大小端问题
  102. // 发送
  103. for (i = 0; i < CAN_BUS_NUM; i++)
  104. {
  105. ret = can_send(i, buf);
  106. if (ret < 0)
  107. {
  108. // rt_printf("can_app_timing:ret=%d\r\n",ret);
  109. }
  110. }
  111. g_timing_sec = ts.tv_sec;
  112. return 0;
  113. }
  114. int can_app_reset(int is_watchdog)
  115. {
  116. int i;
  117. u8 *buf;
  118. // 帧头
  119. buf = can_request_tx_buf(CAN_FRAME_TYPE_RESET);
  120. buf[0] = CAN_FRAME_TYPE_RESET;
  121. buf[1] = CAN_BUS_ADDR_BCAST;
  122. buf[2] = 0;
  123. buf[3] = 1;
  124. buf[4] = (u8)is_watchdog;
  125. // 发送
  126. for (i = 0; i < CAN_BUS_NUM; i++)
  127. {
  128. can_send(i, buf);
  129. }
  130. // 子板复位时更新时间,避免产生子板通讯异常错误。
  131. for (i = 0; i < EQU_SLOT_NUM_MAX; i++)
  132. {
  133. g_board_info[i].us0 = ustimer_get_origin();
  134. }
  135. return 0;
  136. }
  137. int can_app_sb_monitor(void)
  138. {
  139. g_sb_monitor = 1;
  140. return 0;
  141. }
  142. int can_app_sb_monitor_send(void)
  143. {
  144. u8 buf[4];
  145. buf[0] = CAN_FRAME_TYPE_SB_MONITOR;
  146. buf[1] = CAN_BUS_ADDR_BCAST;
  147. buf[2] = 0;
  148. buf[3] = 0;
  149. // 发送
  150. can_send(0, buf);
  151. can_send(1, buf);
  152. return 0;
  153. }
  154. // can子板查询 oujie add 20200420
  155. int can_app_sb_discover(void)
  156. {
  157. u8 buf[4];
  158. u32 slot;
  159. slot = equ_get_slot_by_type(BOARD_TYPE_METERING);
  160. if (slot > 0)
  161. {
  162. buf[0] = CAN_FRAME_TYPE_DISCOVER;
  163. buf[1] = CAN_BUS_ADDR_BCAST;
  164. buf[2] = 0;
  165. buf[3] = 0;
  166. #ifdef CAN_BOARD_DEBUG
  167. rt_printf("查询子板\r\n");
  168. #endif
  169. // 发送
  170. can_send(0, buf);
  171. // can_send(1,buf);
  172. }
  173. return 0;
  174. }
  175. #if 1
  176. // 分配can子板卡槽号 oujie add 20200420
  177. int can_app_sb_give_slot(u32 no, u8 *buf)
  178. {
  179. u8 send_buf[32];
  180. char id_string[64] = {0};
  181. struct can_board_res *can_brd;
  182. Hex2Str(&buf[5], id_string, CHIP_ID_SIZE * 4);
  183. #ifdef CAN_BOARD_DEBUG
  184. rt_printf("子板id字符串 = %s\r\n", id_string);
  185. rt_printf("获取卡槽号\r\n");
  186. #endif
  187. can_brd = equ_get_can_slot(buf[4], buf[5], &buf[6], sizeof(can_brd->chip_id));
  188. if (can_brd != NULL)
  189. {
  190. can_brd->type = buf[5];
  191. send_buf[0] = CAN_FRAME_TYPE_GIVE_CAN_SLOT;
  192. send_buf[1] = CAN_BUS_ADDR_BCAST;
  193. send_buf[2] = 0;
  194. send_buf[3] = sizeof(can_brd->chip_id) + 1;
  195. send_buf[4] = can_brd->slot;
  196. memcpy(&send_buf[5], can_brd->chip_id, sizeof(can_brd->chip_id));
  197. #ifdef CAN_BOARD_DEBUG
  198. rt_printf("CAN发送卡槽号 slot = %d\r\n", can_brd->slot);
  199. rt_printf("CAN卡类型 type = %d\r\n", can_brd->type);
  200. #endif
  201. // 发送
  202. can_send(no, send_buf);
  203. }
  204. else
  205. {
  206. #ifdef CAN_BOARD_DEBUG
  207. rt_printf("卡槽号已存在,不再发送\r\n");
  208. #endif
  209. }
  210. return 0;
  211. }
  212. #endif
  213. struct sb_monitor
  214. {
  215. // 系统
  216. u32 slot;
  217. u32 type;
  218. u32 start_sec;
  219. // 中断时间
  220. u32 us_gps_min;
  221. u32 us_gps_max;
  222. u32 us_100us_min;
  223. u32 us_100us_max;
  224. u32 us_can_min;
  225. u32 us_can_max;
  226. // 开出
  227. u32 do_delay_min;
  228. u32 do_delay_max;
  229. // CAN总线
  230. u32 can_rx_dropped;
  231. u32 can_tx_dropped;
  232. u32 can_hw_bus_errors;
  233. u32 can_hw_errors;
  234. u32 can_hw_overrun;
  235. u32 can_overrun;
  236. };
  237. extern struct rt_stat g_stat_do_delay;
  238. int can_app_sb_monitor_recv(u8 *buf)
  239. {
  240. struct sb_monitor sm;
  241. struct timespec ts;
  242. memcpy(&sm, &buf[4], sizeof(sm));
  243. rt_printf("\r\n子板监视信息[slot=%02d,type=%02d]:\r\n", sm.slot, sm.type);
  244. ts.tv_sec = sm.start_sec;
  245. ts.tv_nsec = 0;
  246. rt_printf("上电时间: ");
  247. rt_printf_time2(ts);
  248. rt_printf(" GPS中断时间:\tmin=%d,\tmax=%d\r\n", sm.us_gps_min, sm.us_gps_max);
  249. rt_printf("100us中断时间:\tmin=%d,\tmax=%d\r\n", sm.us_100us_min, sm.us_100us_max);
  250. rt_printf(" CAN中断时间:\tmin=%d,\tmax=%d\r\n", sm.us_can_min, sm.us_can_max);
  251. rt_printf(" 开出延时时间:\tmin=%d,\tmax=%d\r\n", sm.do_delay_min, sm.do_delay_max);
  252. rt_stat_in(&g_stat_do_delay, sm.do_delay_max);
  253. rt_printf("CAN总线接收丢包:%d\r\n", sm.can_rx_dropped);
  254. rt_printf("CAN总线发送丢包:%d\r\n", sm.can_tx_dropped);
  255. rt_printf("CAN总线总线错误:%d\r\n", sm.can_hw_bus_errors);
  256. rt_printf("CAN总线硬件错误:%d\r\n", sm.can_hw_errors);
  257. rt_printf("CAN总线硬件溢出:%d\r\n", sm.can_hw_overrun);
  258. rt_printf("CAN总线接收溢出:%d\r\n", sm.can_overrun);
  259. return 0;
  260. }
  261. int can_app_sb_discover_recv(u8 *buf)
  262. {
  263. struct can_board_res *can_brd;
  264. #ifdef CAN_BOARD_DEBUG
  265. uint8_t i;
  266. #endif
  267. memcpy((u8 *)can_board[0].chip_id, &buf[6], sizeof(can_brd->chip_id));
  268. #ifdef CAN_BOARD_DEBUG
  269. rt_printf("\r\n接收到子板chip_id: ");
  270. for (i = 0; i < sizeof(can_brd->chip_id); i++)
  271. {
  272. rt_printf("%x ", buf[6 + i]);
  273. }
  274. rt_printf("\r\n");
  275. #endif
  276. return 0;
  277. }
  278. int can_app_sb_slot_recv(u8 *buf)
  279. {
  280. #ifdef CAN_BOARD_DEBUG
  281. rt_printf("接收到子板分配卡槽的应答\r\n");
  282. #endif
  283. uint8_t i;
  284. for (i = 0; i < CAN_BOARD_NUM; i++)
  285. {
  286. if (can_board[i].file_have)
  287. {
  288. if ((memcmp((u8 *)can_board[i].chip_id, &buf[5], sizeof(can_board[i].chip_id)) == 0) && (can_board[i].slot == buf[4]))
  289. {
  290. #ifdef CAN_BOARD_DEBUG
  291. rt_printf("分配子板号完成\r\n");
  292. #endif
  293. can_board[i].given_slot = 1;
  294. }
  295. }
  296. }
  297. return 0;
  298. }
  299. int errcount_crc = 0;
  300. int errcount_sb = 0;
  301. int errcount_no = 0;
  302. int errcount_sb_no = 0;
  303. int errcount_check = 0;
  304. static u32 g_no_send[CAN_BUS_NUM];
  305. static u32 g_no_recv[EQU_SLOT_NUM_MAX];
  306. int can_app_test_send(void)
  307. {
  308. u8 *buf_tx;
  309. int i, can, no, len, ret;
  310. len = 200;
  311. buf_tx = can_request_tx_buf(CAN_FRAME_TYPE_TEST);
  312. for (can = 0; can < CAN_BUS_NUM; can++)
  313. {
  314. no = g_no_send[can];
  315. buf_tx[0] = CAN_FRAME_TYPE_TEST;
  316. buf_tx[1] = CAN_BUS_ADDR_BCAST;
  317. buf_tx[2] = 0;
  318. buf_tx[3] = len;
  319. buf_tx[4] = 0;
  320. buf_tx[5] = no;
  321. buf_tx[6] = no >> 8;
  322. buf_tx[7] = no >> 16;
  323. buf_tx[8] = no >> 24;
  324. for (i = 0; i < (len - 6); i++)
  325. {
  326. buf_tx[i + 9] = i;
  327. }
  328. buf_tx[len + 3] = can_app_checksum(buf_tx + 4, len - 1);
  329. // 发送
  330. ret = can_send(can, buf_tx);
  331. if (ret < 0)
  332. {
  333. if (ret != -7)
  334. {
  335. rt_printf("can_app_test error:ret=%d\r\n", ret);
  336. }
  337. }
  338. else
  339. {
  340. g_no_send[can]++;
  341. }
  342. }
  343. return 0;
  344. }
  345. int can_app_test_recv(u8 *buf)
  346. {
  347. u8 len, crc, crc_check;
  348. int i, no, slot;
  349. slot = buf[2];
  350. len = buf[3];
  351. crc = buf[len + 3];
  352. crc_check = can_app_checksum(buf + 4, len - 1);
  353. no = buf[5] | ((int)buf[6]) << 8 | ((int)buf[7]) << 16 | ((int)buf[8]) << 24;
  354. // 检查CRC
  355. if (crc != crc_check)
  356. {
  357. errcount_crc++;
  358. rt_printf("can_app_test_recv:crc error!slot=%d,type=%d,no=%d, crc=%x,crc_check=%x,errcount_crc=%d\r\n", slot, buf[4], no, crc, crc_check, errcount_crc);
  359. print_msg("RX_CAN:", buf, buf[3] + 4);
  360. return -1;
  361. }
  362. // 检查子板接收错误
  363. if (buf[4] != 0)
  364. {
  365. errcount_sb++;
  366. rt_printf("can_app_test_recv:sb error! slot=%d,type=%d,no=%d, errcount_sb=%d\r\n", slot, buf[4], no, errcount_sb);
  367. print_msg("RX_CAN:", buf, buf[3] + 4);
  368. return -2;
  369. }
  370. // 检查内容
  371. for (i = 0; i < (len - 6); i++)
  372. {
  373. if (buf[i + 9] != i)
  374. {
  375. break;
  376. }
  377. }
  378. if (i != (len - 6))
  379. {
  380. errcount_check++;
  381. rt_printf("can_app_test_recv:content error!slot=%d,no=%d,errcount_check=%d\r\n", slot, no, errcount_check);
  382. print_msg("RX_CAN:", buf, buf[3] + 4);
  383. return -4;
  384. }
  385. // 检查序号
  386. if (no != g_no_recv[slot])
  387. {
  388. errcount_sb_no++;
  389. rt_printf("can_app_test_recv:no error!slot=%d,no=%d,g_no_recv[slot]=%d,errcount_sb_no=%d\r\n", slot, no, g_no_recv[slot], errcount_sb_no);
  390. print_msg("RX_CAN:", buf, buf[3] + 4);
  391. return -5;
  392. }
  393. // 检查ok,序号加一
  394. g_no_recv[slot]++;
  395. return 0;
  396. }
  397. int can_task(void)
  398. {
  399. int i;
  400. u8 *buf;
  401. struct can_frame_head *cfh;
  402. static unsigned char send_discover = 0;
  403. #ifdef CAN_SLAVE_BOARD
  404. static unsigned long us0 = 0;
  405. static unsigned long us1 = 0;
  406. static unsigned char send_discover = 0;
  407. #endif
  408. // static unsigned long us1 = 0;
  409. u8 can_no = 0;
  410. if (g_sb_monitor)
  411. {
  412. can_app_sb_monitor_send();
  413. g_sb_monitor = 0;
  414. }
  415. buf = can_request_tx_buf(CAN_FRAME_TYPE_PROGRAM_UPDATE);
  416. // 最多一次接收8帧
  417. for (i = 0; i < 128; i++)
  418. {
  419. if (can_recv(0, buf, CAN_FRAME_LEN_MAX) <= 0)
  420. {
  421. if (can_recv(1, buf, CAN_FRAME_LEN_MAX) <= 0)
  422. {
  423. prog_recv_timeout();
  424. break;
  425. }
  426. else
  427. can_no = 1;
  428. }
  429. else
  430. can_no = 0;
  431. // 检查帧内容
  432. cfh = (struct can_frame_head *)buf;
  433. #if 0
  434. if(cfh->src >= EQU_SLOT_NUM_MAX)
  435. {
  436. continue;
  437. }
  438. #endif
  439. if (cfh->src >= (EQU_SLOT_NUM_MAX + CAN_BOARD_NUM))
  440. {
  441. continue;
  442. }
  443. // 处理不同类型的帧
  444. switch (cfh->type)
  445. {
  446. case CAN_FRAME_TYPE_PROGRAM_UPDATE:
  447. prog_recv(buf);
  448. break;
  449. case CAN_FRAME_TYPE_SB_MONITOR:
  450. can_app_sb_monitor_recv(buf);
  451. break;
  452. case CAN_FRAME_TYPE_TEST:
  453. if (can_app_test_recv(buf) != 0)
  454. {
  455. g_test_on = 0;
  456. g_print_can = 0;
  457. }
  458. break;
  459. case CAN_FRAME_TYPE_DISCOVER:
  460. can_app_sb_discover_recv(buf);
  461. can_app_sb_give_slot(can_no, buf);
  462. send_discover = 0;
  463. can_brd_error_clear(buf[4]);
  464. break;
  465. case CAN_FRAME_TYPE_GIVE_CAN_SLOT: // 收到子板应答
  466. can_app_sb_slot_recv(buf);
  467. break;
  468. default:
  469. break;
  470. }
  471. }
  472. // 子板程序更新发送
  473. prog_send();
  474. #ifdef CAN_SLAVE_BOARD
  475. if (!is_prog_down())
  476. {
  477. if (us0 == 0)
  478. us0 = ustimer_get_origin();
  479. if (ustimer_delay_origin2(&us0, 3 * USTIMER_SEC))
  480. {
  481. us0 = 0;
  482. can_app_sb_discover();
  483. send_discover++;
  484. us1 = ustimer_get_origin();
  485. }
  486. if (send_discover >= 2)
  487. {
  488. if (ustimer_delay_origin2(&us1, 2 * USTIMER_SEC))
  489. {
  490. send_discover = 0;
  491. us1 = ustimer_get_origin();
  492. can_brd_error_set();
  493. // rt_printf("can_brd_error_set\r\n");
  494. }
  495. }
  496. }
  497. #endif
  498. #if defined(METERING_ENERGY) && defined(CAN_SLAVE_BOARD)
  499. if (!is_prog_down() && !send_discover)
  500. can_metering_send_app();
  501. #endif
  502. if (g_test_on)
  503. {
  504. // can_app_test_send();
  505. }
  506. return 0;
  507. }
  508. int can_app_test_printf(void)
  509. {
  510. int i;
  511. for (i = 0; i < CAN_BUS_NUM; i++)
  512. {
  513. rt_printf("slot%02d:%d.\r\n", i, g_no_send[i]);
  514. }
  515. rt_printf("g_no_recv:\r\n");
  516. for (i = 0; i < EQU_SLOT_NUM_MAX; i++)
  517. {
  518. rt_printf("slot%02d:%d.\r\n", i, g_no_recv[i]);
  519. }
  520. return 0;
  521. }
  522. #endif
  523. /*------------------------------ 内部函数 -------------------------------------
  524. 内部函数以下划线‘_’开头,不需要检查参数的合法性.
  525. */
  526. /*------------------------------ 测试函数 -------------------------------------
  527. 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
  528. 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
  529. */
  530. /*------------------------------ 文件结束 -------------------------------------
  531. */