You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

425 lines
15 KiB

3 months ago
  1. #include "zcanreceiver.hpp"
  2. #include "stm32basic/mutex.hpp"
  3. #include "stm32halport/stm32halport.hpp"
  4. #define TAG "zcan"
  5. #define CANHANDLER &hcan1
  6. #define CAN_FILTER_INDEX 0
  7. #define CAN_MAX_FILTER_NUM 7
  8. #define CAN_FIFO_NUM CAN_RX_FIFO0
  9. #define OVER_TIME_MS 30
  10. #define HEART_OVERTIME (30 * 1000)
  11. using namespace iflytop;
  12. static uint8_t m_deviceId;
  13. static zcanbus_on_rx_t m_rxlistener[30];
  14. static uint32_t m_numListener = 0;
  15. static zcanbus_on_connected_t m_connectedlistener;
  16. static canrxbuffer_t m_rxbufcache;
  17. static uint16_t reportIndex;
  18. static uint8_t rxdata[200];
  19. static uint8_t txbuff[200];
  20. static uint32_t lastpacket_ticket;
  21. static bool m_is_connected;
  22. static uint8_t m_priority;
  23. zmutex m_lock = {"ZCANReceiver"};
  24. static void _oncanpacket(CAN_HandleTypeDef *hcan);
  25. static void _processOneCanPacket(CAN_RxHeaderTypeDef *pHeader, uint8_t *aData);
  26. static bool _getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/);
  27. extern "C" {
  28. void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0CompleteCallback"); }
  29. void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1CompleteCallback"); }
  30. void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2CompleteCallback"); }
  31. void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0AbortCallback"); }
  32. void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1AbortCallback"); }
  33. void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2AbortCallback"); }
  34. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { _oncanpacket(hcan); }
  35. void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo0FullCallback"); }
  36. void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1MsgPendingCallback"); }
  37. void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1FullCallback"); }
  38. void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_SleepCallback"); }
  39. void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_WakeUpFromRxMsgCallback"); }
  40. void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_ErrorCallback"); }
  41. }
  42. /***********************************************************************************************************************
  43. * ?? *
  44. ***********************************************************************************************************************/
  45. static void _oncanpacket(CAN_HandleTypeDef *hcan) {
  46. if (CANHANDLER != hcan) return;
  47. CAN_RxHeaderTypeDef pHeader;
  48. uint8_t aData[8] /*8byte table*/;
  49. while (_getRxMessage(&pHeader, aData)) {
  50. _processOneCanPacket(&pHeader, aData);
  51. }
  52. }
  53. static bool _getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/) {
  54. /**
  55. * @brief FIFO??
  56. */
  57. uint32_t level = HAL_CAN_GetRxFifoFillLevel(CANHANDLER, CAN_FIFO_NUM);
  58. if (level == 0) {
  59. return false;
  60. }
  61. HAL_StatusTypeDef HAL_RetVal;
  62. HAL_RetVal = HAL_CAN_GetRxMessage(CANHANDLER, CAN_FIFO_NUM, pHeader, aData);
  63. if (HAL_OK == HAL_RetVal) {
  64. // 处理接收到的can总线数据
  65. return true;
  66. }
  67. return false;
  68. }
  69. static void _processOneCanPacket(CAN_RxHeaderTypeDef *pHeader, uint8_t *aData) {
  70. /**
  71. * @brief 12bit from,1bit emergency
  72. *
  73. * [1] [4bit] [8bit] [8bit] [4bit/4bit]
  74. * , from to frameNum/frameId
  75. */
  76. uint8_t from = (pHeader->ExtId & 0x00FF0000) >> 16;
  77. uint8_t to = (pHeader->ExtId & 0x0000FF00) >> 8;
  78. uint8_t nframe = (pHeader->ExtId & 0x000000F0) >> 4;
  79. uint8_t frameId = (pHeader->ExtId & 0x0000000F);
  80. // ZLOGI(TAG, "from:%d to:%d nframe:%d frameId:%d", from, to, nframe, frameId);
  81. if (pHeader->IDE == CAN_ID_STD) {
  82. return;
  83. }
  84. // ��?接收主机消息
  85. if (from != 1) {
  86. return;
  87. }
  88. if (to != m_deviceId && to != 0xff) {
  89. return;
  90. }
  91. // 上�?�接收到的消��?还没有来的急�?�理
  92. if (m_rxbufcache.dataIsReady) {
  93. ZLOGI(TAG, "discard rx packet ,last packet not processed");
  94. return;
  95. }
  96. if (frameId == 0) {
  97. m_rxbufcache.canPacketNum = 0;
  98. }
  99. if (frameId != m_rxbufcache.canPacketNum) {
  100. m_rxbufcache.canPacketNum = 0;
  101. ZLOGI(TAG, "discard rx packet ,due to lost packet");
  102. return;
  103. }
  104. if (m_rxbufcache.canPacketNum < ZARRAY_SIZE(m_rxbufcache.canPacket)) {
  105. if (m_rxbufcache.canPacketNum == 0) {
  106. m_rxbufcache.header = *pHeader;
  107. m_rxbufcache.from = from;
  108. m_rxbufcache.to = to;
  109. }
  110. m_rxbufcache.canPacket[m_rxbufcache.canPacketNum].datalen = pHeader->DLC;
  111. memcpy(m_rxbufcache.canPacket[m_rxbufcache.canPacketNum].aData, aData, 8);
  112. m_rxbufcache.canPacketNum++;
  113. } else {
  114. ZLOGI(TAG, "discard rx packet ,due to buffer full");
  115. m_rxbufcache.canPacketNum = 0;
  116. return;
  117. }
  118. if (nframe == frameId + 1) {
  119. if (m_rxbufcache.canPacketNum != nframe) {
  120. m_rxbufcache.canPacketNum = 0;
  121. ZLOGI(TAG, "discard rx packet ,due to lost packet");
  122. return;
  123. } else {
  124. m_rxbufcache.dataIsReady = true;
  125. }
  126. }
  127. }
  128. /***********************************************************************************************************************
  129. * FUNC *
  130. ***********************************************************************************************************************/
  131. static HAL_StatusTypeDef activateRxIT() {
  132. HAL_StatusTypeDef hal_status = HAL_ERROR;
  133. if (CAN_FIFO_NUM == CAN_RX_FIFO0) {
  134. hal_status = HAL_CAN_ActivateNotification(CANHANDLER, CAN_IT_RX_FIFO0_MSG_PENDING);
  135. } else if (CAN_FIFO_NUM == CAN_RX_FIFO1) {
  136. hal_status = HAL_CAN_ActivateNotification(CANHANDLER, CAN_IT_RX_FIFO1_MSG_PENDING);
  137. } else {
  138. ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n");
  139. return hal_status;
  140. }
  141. return hal_status;
  142. }
  143. // static HAL_StatusTypeDef deactivateRxIT() {
  144. // HAL_StatusTypeDef hal_status = HAL_ERROR;
  145. // if (CAN_FIFO_NUM == CAN_RX_FIFO0) {
  146. // hal_status = HAL_CAN_DeactivateNotification(CANHANDLER, CAN_IT_RX_FIFO0_MSG_PENDING);
  147. // } else if (CAN_FIFO_NUM == CAN_RX_FIFO1) {
  148. // hal_status = HAL_CAN_DeactivateNotification(CANHANDLER, CAN_IT_RX_FIFO1_MSG_PENDING);
  149. // } else {
  150. // ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n");
  151. // return hal_status;
  152. // }
  153. // return hal_status;
  154. // }
  155. HAL_StatusTypeDef initializeFilter() {
  156. HAL_StatusTypeDef HAL_Status;
  157. CAN_FilterTypeDef sFilterConfig;
  158. uint32_t filterId;
  159. uint32_t mask;
  160. memset(&sFilterConfig, 0, sizeof(sFilterConfig));
  161. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式
  162. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
  163. sFilterConfig.FilterFIFOAssignment = CAN_FIFO_NUM; // 关联过滤器到rxfifoNum
  164. sFilterConfig.FilterActivation = ENABLE; // 激活过滤器
  165. sFilterConfig.SlaveStartFilterBank = CAN_MAX_FILTER_NUM; // slave filter start index
  166. /*******************************************************************************
  167. * ? *
  168. *******************************************************************************/
  169. filterId = (0); //
  170. mask = (0); //
  171. sFilterConfig.FilterBank = CAN_FILTER_INDEX; //
  172. sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
  173. sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
  174. sFilterConfig.FilterIdLow = filterId & 0xffff; //
  175. sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
  176. HAL_Status = HAL_CAN_ConfigFilter(CANHANDLER, &sFilterConfig);
  177. if (HAL_Status != HAL_OK) {
  178. ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail");
  179. return HAL_Status;
  180. }
  181. // ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3);
  182. return HAL_Status;
  183. }
  184. void zcanbus_init(uint8_t deviceId) {
  185. m_deviceId = deviceId;
  186. HAL_StatusTypeDef hal_status;
  187. m_rxbufcache.dataIsReady = false;
  188. m_rxbufcache.id = 0; // ��?接收来自主机的消��?
  189. m_rxbufcache.canPacketNum = 0;
  190. hal_status = initializeFilter();
  191. if (hal_status != HAL_OK) {
  192. ZLOGE(TAG, "start can initializeFilter fail\r\n");
  193. return;
  194. }
  195. hal_status = HAL_CAN_Start(CANHANDLER); // 开启CAN
  196. if (hal_status != HAL_OK) {
  197. ZLOGE(TAG, "start can fail\r\n");
  198. return;
  199. }
  200. m_lock.init();
  201. HAL_StatusTypeDef status = activateRxIT();
  202. if (status != HAL_OK) {
  203. ZLOGE(TAG, "activateRxIT fail\r\n");
  204. ZASSERT(0);
  205. return;
  206. }
  207. ZLOGI(TAG, "zcanbus init done");
  208. }
  209. void zcanbus_reglistener(zcanbus_on_rx_t rxlistener) {
  210. ZASSERT(m_numListener < ZARRAY_SIZE(m_rxlistener));
  211. m_rxlistener[m_numListener++] = rxlistener;
  212. }
  213. void zcanbus_reg_on_connected_listener(zcanbus_on_connected_t connectedlistener) { m_connectedlistener = connectedlistener; }
  214. bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len) { return zcanbus_send_packet(to, packet, len, OVER_TIME_MS); }
  215. static char *hex2str(uint8_t *data, size_t len) {
  216. static char buf[200];
  217. memset(buf, 0, sizeof(buf));
  218. for (size_t i = 0; i < len; i++) {
  219. sprintf(buf + i * 2, "%02x", data[i]);
  220. }
  221. return buf;
  222. }
  223. bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len, int overtimems) {
  224. ZLOGI(TAG, "sendPacket to:%d, %s(%d)", to, hex2str(packet, len), len);
  225. int npacket = len / 8 + (len % 8 == 0 ? 0 : 1);
  226. if (npacket > 255) {
  227. ZLOGE(TAG, "sendPacket fail, len:%d", len);
  228. return false;
  229. }
  230. int finalpacketlen = len % 8 == 0 ? 8 : len % 8;
  231. for (uint8_t i = 0; i < npacket; i++) {
  232. bool suc = false;
  233. if (i == npacket - 1) {
  234. suc = zcanbus_send_sub_packet(to, npacket, i, packet + i * 8, finalpacketlen, overtimems);
  235. } else {
  236. suc = zcanbus_send_sub_packet(to, npacket, i, packet + i * 8, 8, overtimems);
  237. }
  238. if (!suc) {
  239. // ZLOGE(TAG, "sendPacket fail, packet(%d:%d)", npacket, i);
  240. return false;
  241. }
  242. }
  243. return true;
  244. }
  245. // static const char *canpacket_dump(uint8_t *data, int size) {
  246. // static char buf[20];
  247. // memset(buf, 0, sizeof(buf));
  248. // for (int i = 0; i < size; i++) {
  249. // sprintf(buf + i * 2, "%02x", data[i]);
  250. // }
  251. // return buf;
  252. // }
  253. bool zcanbus_send_sub_packet(uint8_t to, int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) {
  254. CAN_TxHeaderTypeDef pHeader;
  255. uint8_t aData[8] /*8byte table*/;
  256. uint32_t txMailBox = 0;
  257. uint32_t enterticket = zget_ticket();
  258. memset(&pHeader, 0, sizeof(pHeader));
  259. memset(aData, 0, sizeof(aData));
  260. pHeader.StdId = 0x00;
  261. pHeader.ExtId = (m_deviceId << 16) | (to << 8) | (npacket << 4) | (packetIndex);
  262. pHeader.ExtId |= (m_priority & 0x0f) << 24;
  263. pHeader.ExtId |= (0x01 << 28);
  264. pHeader.IDE = CAN_ID_EXT;
  265. pHeader.RTR = CAN_RTR_DATA;
  266. pHeader.DLC = len;
  267. pHeader.TransmitGlobalTime = DISABLE;
  268. memcpy(aData, packet, len);
  269. // ZLOGI(TAG, "tx %s", canpacket_dump(aData, len));
  270. HAL_StatusTypeDef lastTransmitStatus = HAL_CAN_AddTxMessage(CANHANDLER, &pHeader, aData, &txMailBox);
  271. if (lastTransmitStatus != HAL_OK) {
  272. ZLOGE(TAG, "HAL_CAN_AddTxMessage fail");
  273. return false;
  274. }
  275. while (HAL_CAN_IsTxMessagePending(CANHANDLER, txMailBox)) {
  276. if (zhas_passedms(enterticket) > (uint32_t)overtimems) {
  277. lastTransmitStatus = HAL_TIMEOUT;
  278. HAL_CAN_AbortTxRequest(CANHANDLER, txMailBox);
  279. return false;
  280. }
  281. zos_delay_ms(1);
  282. }
  283. return true;
  284. }
  285. bool zcanbus_send_ack(zcanbus_packet_t *rxpacket, uint8_t *param, size_t len) {
  286. zlock_guard l(m_lock);
  287. zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff;
  288. txpacket->index = rxpacket->index;
  289. txpacket->function_id = rxpacket->function_id;
  290. txpacket->ptype = kreceipt;
  291. if (param) memcpy(txpacket->params, param, len);
  292. return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len);
  293. }
  294. bool zcanbus_send_ack(zcanbus_packet_t *rxpacket, int32_t val) { return zcanbus_send_ack(rxpacket, (uint8_t *)&val, sizeof(val)); }
  295. bool zcanbus_send_ack(zcanbus_packet_t *rxpacket, bool _val) {
  296. int32_t val = _val ? 1 : 0;
  297. return zcanbus_send_ack(rxpacket, (uint8_t *)&val, sizeof(val));
  298. }
  299. bool zcanbus_send_errorack(zcanbus_packet_t *rxpacket, int32_t errcode) {
  300. zlock_guard l(m_lock);
  301. m_priority = kpriority_receipt;
  302. zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff;
  303. txpacket->index = rxpacket->index;
  304. txpacket->function_id = rxpacket->function_id;
  305. txpacket->ptype = kerror_receipt;
  306. memcpy(txpacket->params, &errcode, sizeof(errcode));
  307. return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + 4);
  308. }
  309. bool zcanbus_send_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime) {
  310. zlock_guard l(m_lock);
  311. m_priority = kpriority_report;
  312. zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff;
  313. txpacket->index = reportIndex++;
  314. txpacket->function_id = function_id;
  315. txpacket->ptype = kreport;
  316. memcpy(txpacket->params, param, len);
  317. return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len, overtime);
  318. }
  319. bool zcanbus_send_emergency_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime) {
  320. zlock_guard l(m_lock);
  321. m_priority = kpriority_emergency_report;
  322. zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff;
  323. txpacket->index = reportIndex++;
  324. txpacket->function_id = function_id;
  325. txpacket->ptype = kreport;
  326. memcpy(txpacket->params, param, len);
  327. return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len, overtime);
  328. }
  329. static void process_rx_packet(canrxbuffer_t *canrxbuf, uint8_t *rx, size_t len) {
  330. zcanbus_packet_t *packet = (zcanbus_packet_t *)rx;
  331. lastpacket_ticket = zget_ticket();
  332. if (!m_is_connected) {
  333. m_is_connected = true;
  334. if (m_connectedlistener) m_connectedlistener(true);
  335. }
  336. if (packet->ptype == kcmd) {
  337. for (size_t i = 0; i < m_numListener; i++) {
  338. m_rxlistener[i](canrxbuf->from, canrxbuf->to, rxdata, len);
  339. }
  340. }
  341. }
  342. void zcanbus_schedule() {
  343. canrxbuffer_t *rxbuf = &m_rxbufcache;
  344. uint16_t fromId = 0;
  345. uint16_t toId = 0;
  346. if (rxbuf->dataIsReady) {
  347. int dataoff = 0;
  348. // rxdata[0] = rxbuf->from;
  349. // rxdata[1] = rxbuf->to;
  350. for (size_t i = 0; i < rxbuf->canPacketNum; i++) {
  351. memcpy(rxdata + dataoff, rxbuf->canPacket[i].aData, rxbuf->canPacket[i].datalen);
  352. dataoff += rxbuf->canPacket[i].datalen;
  353. ZASSERT(dataoff < ZARRAY_SIZE(rxdata));
  354. }
  355. process_rx_packet(rxbuf, rxdata, dataoff);
  356. rxbuf->dataIsReady = false;
  357. }
  358. if (m_is_connected && zhas_passedms(lastpacket_ticket) > HEART_OVERTIME) {
  359. m_is_connected = false;
  360. if (m_connectedlistener) m_connectedlistener(false);
  361. }
  362. }
  363. bool zcanbus_is_connected() { return m_is_connected; }