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.

350 lines
12 KiB

12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
  1. #include "zcanreceiver.hpp"
  2. #ifdef HAL_CAN_MODULE_ENABLED
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "stm32basic/zbasic.h"
  7. #define TAG "ZCanReceiver"
  8. #define OVER_TIME_MS 100
  9. #ifdef ENABLE_OLD_CAN_PROTOCOL
  10. #include "stm32halport/stm32halport.hpp"
  11. extern "C" {
  12. void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0CompleteCallback"); }
  13. void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1CompleteCallback"); }
  14. void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2CompleteCallback"); }
  15. void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0AbortCallback"); }
  16. void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1AbortCallback"); }
  17. void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2AbortCallback"); }
  18. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_RxFifo0MsgPending(hcan); }
  19. void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo0FullCallback"); }
  20. void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1MsgPendingCallback"); }
  21. void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1FullCallback"); }
  22. void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_SleepCallback"); }
  23. void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_WakeUpFromRxMsgCallback"); }
  24. void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_Error(hcan); }
  25. }
  26. ZCanReceiver *ZCanReceiver::ins() {
  27. static ZCanReceiver ins;
  28. return &ins;
  29. }
  30. ZCanReceiver::CFG *ZCanReceiver::createCFG(uint8_t deviceId) {
  31. CFG *cfg = new CFG();
  32. ZASSERT(cfg != NULL);
  33. cfg->deviceId = deviceId;
  34. #ifdef STM32F103xB
  35. cfg->canHandle = &hcan;
  36. #else
  37. cfg->canHandle = &hcan1;
  38. #endif
  39. cfg->canFilterIndex0 = 0;
  40. cfg->maxFilterNum = 7;
  41. cfg->rxfifoNum = CAN_RX_FIFO0;
  42. return cfg;
  43. }
  44. void ZCanReceiver::init(CFG *cfg) {
  45. HAL_StatusTypeDef hal_status;
  46. m_config = cfg;
  47. /**
  48. * @brief CAN
  49. */
  50. /**
  51. * @brief buf
  52. */
  53. m_canPacketRxBuffer[0].dataIsReady = false;
  54. m_canPacketRxBuffer[0].id = 1; // 只接收来自主机的消息
  55. m_canPacketRxBuffer[0].m_canPacketNum = 0;
  56. /**
  57. * @brief
  58. */
  59. hal_status = initializeFilter();
  60. if (hal_status != HAL_OK) {
  61. ZLOGE(TAG, "start can initializeFilter fail\r\n");
  62. return;
  63. }
  64. /**
  65. * @brief CAN
  66. */
  67. hal_status = HAL_CAN_Start(m_config->canHandle); // 开启CAN
  68. if (hal_status != HAL_OK) {
  69. ZLOGE(TAG, "start can fail\r\n");
  70. return;
  71. }
  72. HAL_StatusTypeDef status = activateRxIT();
  73. if (status != HAL_OK) {
  74. ZLOGE(TAG, "activateRxIT fail\r\n");
  75. return;
  76. }
  77. }
  78. HAL_StatusTypeDef ZCanReceiver::initializeFilter() {
  79. /**
  80. * @brief ID区帧格式
  81. * [ 27:0 ]
  82. * [ STDID ] [ EXTID ]
  83. * [11 :9] [8:6] [5:0] [17:16] [15:8] [7:0]
  84. * ID ID
  85. */
  86. HAL_StatusTypeDef HAL_Status;
  87. CAN_FilterTypeDef sFilterConfig;
  88. uint32_t filterId;
  89. uint32_t mask;
  90. memset(&sFilterConfig, 0, sizeof(sFilterConfig));
  91. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式
  92. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
  93. sFilterConfig.FilterFIFOAssignment = m_config->rxfifoNum; // 关联过滤器到rxfifoNum
  94. sFilterConfig.FilterActivation = ENABLE; // 激活过滤器
  95. sFilterConfig.SlaveStartFilterBank = m_config->maxFilterNum; // slave filter start index
  96. /*******************************************************************************
  97. * *
  98. *******************************************************************************/
  99. filterId = (0); //
  100. mask = (0); //
  101. sFilterConfig.FilterBank = m_config->canFilterIndex0; //
  102. sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
  103. sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
  104. sFilterConfig.FilterIdLow = filterId & 0xffff; //
  105. sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
  106. HAL_Status = HAL_CAN_ConfigFilter(m_config->canHandle, &sFilterConfig);
  107. if (HAL_Status != HAL_OK) {
  108. ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail");
  109. return HAL_Status;
  110. }
  111. ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3);
  112. return HAL_Status;
  113. }
  114. void ZCanReceiver::registerListener(zcanbus_on_rx_t listener) { m_onRxData = listener; }
  115. void ZCanReceiver::sendPacket(uint8_t *packet, size_t len, int overtime) {
  116. /**
  117. * @brief
  118. */
  119. int npacket = len / 8 + (len % 8 == 0 ? 0 : 1);
  120. if (npacket > 255) {
  121. ZLOGE(TAG, "sendPacket fail, len:%d", len);
  122. return;
  123. }
  124. int finalpacketlen = len % 8 == 0 ? 8 : len % 8;
  125. for (uint8_t i = 0; i < npacket; i++) {
  126. bool suc = false;
  127. if (i == npacket - 1) {
  128. suc = sendPacketSub(npacket, i, packet + i * 8, finalpacketlen, overtime);
  129. } else {
  130. suc = sendPacketSub(npacket, i, packet + i * 8, 8, overtime);
  131. }
  132. if (!suc) {
  133. ZLOGE(TAG, "sendPacket fail, packet(%d:%d)", npacket, i);
  134. return;
  135. }
  136. }
  137. }
  138. void ZCanReceiver::sendAck(transmit_disinfection_protocol_header_t *cmdheader, uint8_t *data, size_t len) {
  139. transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff;
  140. memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t));
  141. txheader->packetType = kpt_ack;
  142. memcpy(txheader->data, data, len);
  143. sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS);
  144. }
  145. void ZCanReceiver::sendErrorAck(transmit_disinfection_protocol_header_t *cmdheader, int16_t errcode) {
  146. transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff;
  147. memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t));
  148. txheader->packetType = kpt_error_ack;
  149. memcpy(txheader->data, &errcode, sizeof(errcode));
  150. sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + 2, OVER_TIME_MS);
  151. }
  152. void ZCanReceiver::sendReport(uint16_t cmdid, uint8_t subcmdid, uint8_t *attachments, size_t len) {
  153. transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff;
  154. txheader->packetindex = report_index++;
  155. txheader->cmdid = cmdid;
  156. txheader->subcmdid = subcmdid;
  157. txheader->packetType = kpt_status_report;
  158. memcpy(txheader->data, attachments, len);
  159. sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS);
  160. }
  161. bool ZCanReceiver::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) {
  162. CAN_TxHeaderTypeDef pHeader;
  163. uint8_t aData[8] /*8byte table*/;
  164. uint32_t txMailBox = 0;
  165. uint32_t enterticket = HAL_GetTick();
  166. memset(&pHeader, 0, sizeof(pHeader));
  167. memset(aData, 0, sizeof(aData));
  168. pHeader.StdId = 0x00;
  169. pHeader.ExtId = (m_config->deviceId << 16) | (npacket << 8) | packetIndex;
  170. pHeader.IDE = CAN_ID_EXT;
  171. pHeader.RTR = CAN_RTR_DATA;
  172. pHeader.DLC = len;
  173. pHeader.TransmitGlobalTime = DISABLE;
  174. memcpy(aData, packet, len);
  175. m_lastTransmitStatus = HAL_CAN_AddTxMessage(m_config->canHandle, &pHeader, aData, &txMailBox);
  176. if (m_lastTransmitStatus != HAL_OK) {
  177. ZLOGE(TAG, "HAL_CAN_AddTxMessage fail");
  178. return false;
  179. }
  180. while (HAL_CAN_IsTxMessagePending(m_config->canHandle, txMailBox)) {
  181. if (zhas_passedms(enterticket) > (uint32_t)overtimems) {
  182. m_lastTransmitStatus = HAL_TIMEOUT;
  183. HAL_CAN_AbortTxRequest(m_config->canHandle, txMailBox);
  184. return false;
  185. }
  186. // m_os->sleepMS(1);
  187. }
  188. return true;
  189. }
  190. bool ZCanReceiver::getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/) {
  191. /**
  192. * @brief FIFO中缓存了多少帧的数据
  193. */
  194. uint32_t level = HAL_CAN_GetRxFifoFillLevel(m_config->canHandle, m_config->rxfifoNum);
  195. if (level == 0) {
  196. return false;
  197. }
  198. HAL_StatusTypeDef HAL_RetVal;
  199. HAL_RetVal = HAL_CAN_GetRxMessage(m_config->canHandle, m_config->rxfifoNum, pHeader, aData);
  200. if (HAL_OK == HAL_RetVal) {
  201. // 处理接收到的can总线数据
  202. return true;
  203. }
  204. return false;
  205. }
  206. void ZCanReceiver::registerListener(CanPacketRxBufferCB_t cb) { m_listenerCBList.push_back(cb); }
  207. void ZCanReceiver::STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *canHandle) {
  208. /**
  209. * @brief
  210. */
  211. // ZLOG_INFO("%s\n", __FUNCTION__);
  212. // printf("------------------%s\n", __FUNCTION__);
  213. if (canHandle != m_config->canHandle) {
  214. return;
  215. }
  216. /**
  217. * @brief can接收到消息
  218. */
  219. CAN_RxHeaderTypeDef pHeader;
  220. uint8_t aData[8] /*8byte table*/;
  221. while (getRxMessage(&pHeader, aData)) {
  222. /**
  223. * @brief
  224. *
  225. * [2] [3bit] [8bit] [8bit] [8bit]
  226. * , from frameNum frameId
  227. */
  228. uint8_t from = (pHeader.ExtId >> 16 & 0xFF);
  229. uint8_t nframe = (pHeader.ExtId & 0xFF00) >> 8;
  230. uint8_t frameId = (pHeader.ExtId & 0x00FF);
  231. CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0];
  232. // CAN_ID_STD
  233. // CAN_ID_EXT
  234. if (pHeader.IDE == CAN_ID_STD) {
  235. // 只接收扩展帧数据帧
  236. continue;
  237. }
  238. if (from != rxbuf->id) {
  239. // 目前只接收来自主机的消息
  240. continue;
  241. }
  242. if (rxbuf->dataIsReady) {
  243. // 上次接收到的消息还没有来的急处理
  244. continue;
  245. }
  246. /**
  247. * @TODO:
  248. */
  249. if (frameId == 0) {
  250. rxbuf->m_canPacketNum = 0;
  251. }
  252. if (rxbuf->m_canPacketNum < 255) {
  253. rxbuf->m_canPacket[rxbuf->m_canPacketNum].pHeader = pHeader;
  254. memcpy(rxbuf->m_canPacket[rxbuf->m_canPacketNum].aData, aData, 8);
  255. rxbuf->m_canPacketNum++;
  256. }
  257. if (nframe == frameId + 1) {
  258. rxbuf->dataIsReady = true;
  259. rxbuf->maxFrameId = frameId;
  260. }
  261. }
  262. // deactivateRxIT();
  263. }
  264. void ZCanReceiver::STM32_HAL_onCAN_Error(CAN_HandleTypeDef *canHandle) {
  265. if (canHandle != m_config->canHandle) {
  266. return;
  267. }
  268. ZLOGE(TAG, "onCAN_Error\r\n");
  269. }
  270. void ZCanReceiver::loop() {
  271. CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0];
  272. if (rxbuf->dataIsReady) {
  273. int dataoff = 0;
  274. for (size_t i = 0; i < rxbuf->m_canPacketNum; i++) {
  275. memcpy(rxdata + dataoff, rxbuf->m_canPacket[i].aData, rxbuf->m_canPacket[i].pHeader.DLC);
  276. dataoff += rxbuf->m_canPacket[i].pHeader.DLC;
  277. memset(&rxbuf->m_canPacket[i], 0, sizeof(rxbuf->m_canPacket[i]));
  278. }
  279. if (m_onRxData) {
  280. m_onRxData(rxbuf, rxdata, dataoff);
  281. }
  282. for (auto &var : m_listenerCBList) {
  283. if (var) var(rxbuf, rxdata, dataoff);
  284. }
  285. rxbuf->dataIsReady = false;
  286. }
  287. }
  288. HAL_StatusTypeDef ZCanReceiver::activateRxIT() {
  289. HAL_StatusTypeDef hal_status = HAL_ERROR;
  290. if (m_config->rxfifoNum == CAN_RX_FIFO0) {
  291. hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);
  292. } else if (m_config->rxfifoNum == CAN_RX_FIFO1) {
  293. hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING);
  294. } else {
  295. ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n");
  296. return hal_status;
  297. }
  298. return hal_status;
  299. }
  300. HAL_StatusTypeDef ZCanReceiver::deactivateRxIT() {
  301. HAL_StatusTypeDef hal_status = HAL_ERROR;
  302. if (m_config->rxfifoNum == CAN_RX_FIFO0) {
  303. hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);
  304. } else if (m_config->rxfifoNum == CAN_RX_FIFO1) {
  305. hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING);
  306. } else {
  307. ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n");
  308. return hal_status;
  309. }
  310. return hal_status;
  311. }
  312. #endif
  313. #endif