can_app.c 12 KB

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