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.

282 lines
8.9 KiB

3 months ago
  1. #include "zcan.hpp"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "stm32halport\halport\gins.h"
  6. using namespace iflytop;
  7. #define TAG "ZCanCmder"
  8. #define OVER_TIME_MS 5
  9. #define FIFO_NUM CAN_RX_FIFO0
  10. extern "C" {
  11. ZCAN1 *zcan1;
  12. void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) {}
  13. void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) {}
  14. void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) {}
  15. void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) {}
  16. void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) {}
  17. void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) {}
  18. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
  19. if (zcan1) zcan1->STM32_HAL_onCAN_RxFifo0MsgPending(hcan);
  20. }
  21. void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) {}
  22. void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {}
  23. void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) {}
  24. void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) {}
  25. void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) {}
  26. void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {}
  27. }
  28. static void can1_init(Pin_t tx, Pin_t rx) {
  29. __HAL_RCC_CAN1_CLK_ENABLE();
  30. GPIO_InitTypeDef GPIO_InitStruct = {0};
  31. if (tx == PA12 && rx == PA11) {
  32. __HAL_RCC_GPIOA_CLK_ENABLE();
  33. GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
  34. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  35. GPIO_InitStruct.Pull = GPIO_NOPULL;
  36. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  37. GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
  38. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  39. } else if (tx == PD1 && rx == PD0) {
  40. __HAL_RCC_GPIOD_CLK_ENABLE();
  41. GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_0;
  42. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  43. GPIO_InitStruct.Pull = GPIO_NOPULL;
  44. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  45. GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
  46. HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  47. } else {
  48. ZASSERT(false);
  49. }
  50. // M1_CAN_RX
  51. // M1_CAN_TX
  52. // static_assert(M1_CAN_RX == PA11);
  53. // static_assert(M1_CAN_TX == PA12);
  54. /* CAN1 interrupt Init */
  55. HAL_NVIC_SetPriority(CAN1_TX_IRQn, 5, 0);
  56. HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
  57. HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 5, 0);
  58. HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
  59. HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 5, 0);
  60. HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
  61. HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 5, 0);
  62. HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
  63. hcan1.Instance = CAN1;
  64. hcan1.Init.Prescaler = 4;
  65. hcan1.Init.Mode = CAN_MODE_NORMAL;
  66. hcan1.Init.SyncJumpWidth = CAN_SJW_3TQ;
  67. hcan1.Init.TimeSeg1 = CAN_BS1_14TQ;
  68. hcan1.Init.TimeSeg2 = CAN_BS2_3TQ;
  69. hcan1.Init.TimeTriggeredMode = ENABLE;
  70. hcan1.Init.AutoBusOff = ENABLE;
  71. hcan1.Init.AutoWakeUp = DISABLE;
  72. hcan1.Init.AutoRetransmission = ENABLE;
  73. hcan1.Init.ReceiveFifoLocked = ENABLE;
  74. hcan1.Init.TransmitFifoPriority = DISABLE;
  75. if (HAL_CAN_Init(&hcan1) != HAL_OK) {
  76. Error_Handler();
  77. }
  78. }
  79. HAL_StatusTypeDef ZCAN1::initializeFilter() {
  80. /**
  81. * @brief ID֡ʽ
  82. * [ 27:0 ]
  83. * [ STDID ] [ EXTID ]
  84. * [11 :9] [8:6] [5:0] [17:16] [15:8] [7:0]
  85. * ȼ ֡ ĿID ԴID
  86. */
  87. HAL_StatusTypeDef HAL_Status;
  88. CAN_FilterTypeDef sFilterConfig;
  89. uint32_t filterId;
  90. uint32_t mask;
  91. memset(&sFilterConfig, 0, sizeof(sFilterConfig));
  92. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // ��ΪMASKģʽ
  93. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
  94. sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; // ������������rxfifoNum
  95. sFilterConfig.FilterActivation = ENABLE; // ����������
  96. sFilterConfig.SlaveStartFilterBank = 7; // slave filter start index
  97. /*******************************************************************************
  98. * Ϣ *
  99. *******************************************************************************/
  100. filterId = (0); //
  101. mask = (0); //
  102. sFilterConfig.FilterBank = 0; //
  103. sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
  104. sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
  105. sFilterConfig.FilterIdLow = filterId & 0xffff; //
  106. sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
  107. HAL_Status = HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
  108. if (HAL_Status != HAL_OK) {
  109. ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail");
  110. return HAL_Status;
  111. }
  112. ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3);
  113. return HAL_Status;
  114. }
  115. HAL_StatusTypeDef ZCAN1::activateRxIT() {
  116. HAL_StatusTypeDef hal_status = HAL_ERROR;
  117. hal_status = HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  118. return hal_status;
  119. }
  120. void ZCAN1::zcaninit(Pin_t tx, Pin_t rx) {
  121. if (inited) return;
  122. inited = true;
  123. can1_init(tx, rx);
  124. HAL_StatusTypeDef hal_status;
  125. m_lock.init();
  126. /**
  127. * @brief ʼ
  128. */
  129. hal_status = initializeFilter();
  130. if (hal_status != HAL_OK) {
  131. ZLOGE(TAG, "start can initializeFilter fail\r\n");
  132. return;
  133. }
  134. /**
  135. * @brief CAN
  136. */
  137. hal_status = HAL_CAN_Start(&hcan1); // ����CAN
  138. if (hal_status != HAL_OK) {
  139. ZLOGE(TAG, "start can fail\r\n");
  140. return;
  141. }
  142. /**
  143. * @brief ص
  144. */
  145. HAL_StatusTypeDef status = activateRxIT();
  146. if (status != HAL_OK) {
  147. ZLOGE(TAG, "activateRxIT fail\r\n");
  148. return;
  149. }
  150. zcan1 = this;
  151. // ZHALCORE::getInstance()->regPeriodJob([this](ZHALCORE::Context &context) { loop(); }, 0);
  152. rxQueue.initialize(5, sizeof(zcanrx_t));
  153. canListener.init("canListener");
  154. canListener.start([this]() {
  155. while (1) {
  156. zcanrx_t rx;
  157. if (rxQueue.receive(&rx, 1000)) {
  158. // ZLOGI(TAG, "zcanrx 0x%08x:%s", rx.extid, zhex2str(rx.rxpacket, rx.rkpacketlen));
  159. if (onZcanRx) onZcanRx(&rx);
  160. }
  161. }
  162. });
  163. }
  164. bool ZCAN1::_txMsg(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) {
  165. zlock_guard l(m_lock);
  166. CAN_TxHeaderTypeDef pHeader;
  167. uint8_t aData[8] /*8byte table*/;
  168. uint32_t txMailBox = 0;
  169. uint32_t enterticket = zos_get_tick();
  170. memset(&pHeader, 0, sizeof(pHeader));
  171. memset(aData, 0, sizeof(aData));
  172. pHeader.StdId = 0x00;
  173. pHeader.ExtId = extid;
  174. pHeader.IDE = CAN_ID_EXT;
  175. pHeader.RTR = CAN_RTR_DATA;
  176. pHeader.DLC = txdatalen;
  177. pHeader.TransmitGlobalTime = DISABLE;
  178. memcpy(aData, txdata, txdatalen);
  179. HAL_StatusTypeDef txsuc = HAL_CAN_AddTxMessage(&hcan1, &pHeader, aData, &txMailBox);
  180. if (txsuc != HAL_OK) {
  181. ZLOGE(TAG, "HAL_CAN_AddTxMessage fail");
  182. return false;
  183. }
  184. int i = 1;
  185. while (HAL_CAN_IsTxMessagePending(&hcan1, txMailBox)) {
  186. if (zos_haspassedms(enterticket) > (uint32_t)overtime) {
  187. if (!txNoError) ZLOGE(TAG, "HAL_CAN_IsTxMessagePending overtime");
  188. HAL_CAN_AbortTxRequest(&hcan1, txMailBox);
  189. return false;
  190. }
  191. osDelay(i);
  192. i++;
  193. }
  194. return true;
  195. }
  196. bool ZCAN1::txMsgNoError(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) {
  197. zlock_guard l(m_lock);
  198. txNoError = true;
  199. bool suc = _txMsg(extid, txdata, txdatalen, overtime);
  200. txNoError = false;
  201. return suc;
  202. }
  203. bool ZCAN1::txMsg(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) {
  204. zlock_guard l(m_lock);
  205. return _txMsg(extid, txdata, txdatalen, overtime);
  206. }
  207. void ZCAN1::regOnCanMessage(function<void(zcanrx_t *rx)> onmessage) { onZcanRx = onmessage; }
  208. bool ZCAN1::getRxMsg(zcanrx_t *rx) {
  209. /**
  210. * @brief ȡǰFIFOл˶֡
  211. */
  212. CAN_RxHeaderTypeDef pHeader;
  213. uint32_t level = HAL_CAN_GetRxFifoFillLevel(&hcan1, FIFO_NUM);
  214. if (level == 0) {
  215. return false;
  216. }
  217. HAL_StatusTypeDef HAL_RetVal;
  218. HAL_RetVal = HAL_CAN_GetRxMessage(&hcan1, FIFO_NUM, &pHeader, rx->rxpacket);
  219. rx->extid = pHeader.ExtId;
  220. rx->rkpacketlen = pHeader.DLC;
  221. if (HAL_OK == HAL_RetVal) {
  222. // �������յ���can��������
  223. return true;
  224. }
  225. return false;
  226. }
  227. static inline const char *zhex2str(uint8_t *data, uint32_t len) {
  228. static char str[256];
  229. for (uint32_t i = 0; i < len; i++) {
  230. sprintf(str + i * 2, "%02X", data[i]);
  231. }
  232. return str;
  233. }
  234. void ZCAN1::STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *canHandle) {
  235. if (canHandle != &hcan1) {
  236. return;
  237. }
  238. /**
  239. * @brief TODO:ʱԴ
  240. */
  241. while (true) {
  242. zcanrx_t rx;
  243. bool rxmsg = getRxMsg(&rx);
  244. if (rxmsg) {
  245. rxQueue.send(&rx, 0);
  246. } else {
  247. break;
  248. }
  249. }
  250. }
  251. void ZCAN1::STM32_HAL_onCAN_Error(CAN_HandleTypeDef *canHandle) { ZLOGE(TAG, "onCAN_Error\r\n"); }