#include "zcan.hpp" #include #include #include #include "stm32halport\halport\gins.h" using namespace iflytop; #define TAG "ZCanCmder" #define OVER_TIME_MS 5 #define FIFO_NUM CAN_RX_FIFO0 extern "C" { ZCAN1 *zcan1; void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { if (zcan1) zcan1->STM32_HAL_onCAN_RxFifo0MsgPending(hcan); } void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) {} void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {} } static void can1_init(Pin_t tx, Pin_t rx) { __HAL_RCC_CAN1_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; if (tx == PA12 && rx == PA11) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_CAN1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } else if (tx == PD1 && rx == PD0) { __HAL_RCC_GPIOD_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_CAN1; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } else { ZASSERT(false); } // M1_CAN_RX // M1_CAN_TX // static_assert(M1_CAN_RX == PA11); // static_assert(M1_CAN_TX == PA12); /* CAN1 interrupt Init */ HAL_NVIC_SetPriority(CAN1_TX_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_TX_IRQn); HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn); HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn); hcan1.Instance = CAN1; hcan1.Init.Prescaler = 4; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_3TQ; hcan1.Init.TimeSeg1 = CAN_BS1_14TQ; hcan1.Init.TimeSeg2 = CAN_BS2_3TQ; hcan1.Init.TimeTriggeredMode = ENABLE; hcan1.Init.AutoBusOff = ENABLE; hcan1.Init.AutoWakeUp = DISABLE; hcan1.Init.AutoRetransmission = ENABLE; hcan1.Init.ReceiveFifoLocked = ENABLE; hcan1.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } } HAL_StatusTypeDef ZCAN1::initializeFilter() { /** * @brief ID区帧格式 * [ 27:0 ] * [ STDID ] [ EXTID ] * [11 :9] [8:6] [5:0] [17:16] [15:8] [7:0] * 优先级 属性 帧类型 目标ID 源ID */ HAL_StatusTypeDef HAL_Status; CAN_FilterTypeDef sFilterConfig; uint32_t filterId; uint32_t mask; memset(&sFilterConfig, 0, sizeof(sFilterConfig)); sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; // 关联过滤器到rxfifoNum sFilterConfig.FilterActivation = ENABLE; // 激活过滤器 sFilterConfig.SlaveStartFilterBank = 7; // slave filter start index /******************************************************************************* * 接收所有消息 * *******************************************************************************/ filterId = (0); // mask = (0); // sFilterConfig.FilterBank = 0; // sFilterConfig.FilterMaskIdLow = mask & 0xffff; // sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; // sFilterConfig.FilterIdLow = filterId & 0xffff; // sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; // HAL_Status = HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig); if (HAL_Status != HAL_OK) { ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail"); return HAL_Status; } ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3); return HAL_Status; } HAL_StatusTypeDef ZCAN1::activateRxIT() { HAL_StatusTypeDef hal_status = HAL_ERROR; hal_status = HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); return hal_status; } void ZCAN1::zcaninit(Pin_t tx, Pin_t rx) { if (inited) return; inited = true; can1_init(tx, rx); HAL_StatusTypeDef hal_status; m_lock.init(); /** * @brief 初始化过滤器 */ hal_status = initializeFilter(); if (hal_status != HAL_OK) { ZLOGE(TAG, "start can initializeFilter fail\r\n"); return; } /** * @brief 启动CAN */ hal_status = HAL_CAN_Start(&hcan1); // 开启CAN if (hal_status != HAL_OK) { ZLOGE(TAG, "start can fail\r\n"); return; } /** * @brief 监听回调 */ HAL_StatusTypeDef status = activateRxIT(); if (status != HAL_OK) { ZLOGE(TAG, "activateRxIT fail\r\n"); return; } zcan1 = this; // ZHALCORE::getInstance()->regPeriodJob([this](ZHALCORE::Context &context) { loop(); }, 0); rxQueue.initialize(5, sizeof(zcanrx_t)); canListener.init("canListener"); canListener.start([this]() { while (1) { zcanrx_t rx; if (rxQueue.receive(&rx, 1000)) { // ZLOGI(TAG, "zcanrx 0x%08x:%s", rx.extid, zhex2str(rx.rxpacket, rx.rkpacketlen)); if (onZcanRx) onZcanRx(&rx); } } }); } bool ZCAN1::_txMsg(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) { zlock_guard l(m_lock); CAN_TxHeaderTypeDef pHeader; uint8_t aData[8] /*8byte table*/; uint32_t txMailBox = 0; uint32_t enterticket = zos_get_tick(); memset(&pHeader, 0, sizeof(pHeader)); memset(aData, 0, sizeof(aData)); pHeader.StdId = 0x00; pHeader.ExtId = extid; pHeader.IDE = CAN_ID_EXT; pHeader.RTR = CAN_RTR_DATA; pHeader.DLC = txdatalen; pHeader.TransmitGlobalTime = DISABLE; memcpy(aData, txdata, txdatalen); HAL_StatusTypeDef txsuc = HAL_CAN_AddTxMessage(&hcan1, &pHeader, aData, &txMailBox); if (txsuc != HAL_OK) { ZLOGE(TAG, "HAL_CAN_AddTxMessage fail"); return false; } int i = 1; while (HAL_CAN_IsTxMessagePending(&hcan1, txMailBox)) { if (zos_haspassedms(enterticket) > (uint32_t)overtime) { if (!txNoError) ZLOGE(TAG, "HAL_CAN_IsTxMessagePending overtime"); HAL_CAN_AbortTxRequest(&hcan1, txMailBox); return false; } osDelay(i); i++; } return true; } bool ZCAN1::txMsgNoError(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) { zlock_guard l(m_lock); txNoError = true; bool suc = _txMsg(extid, txdata, txdatalen, overtime); txNoError = false; return suc; } bool ZCAN1::txMsg(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime) { zlock_guard l(m_lock); return _txMsg(extid, txdata, txdatalen, overtime); } void ZCAN1::regOnCanMessage(function onmessage) { onZcanRx = onmessage; } bool ZCAN1::getRxMsg(zcanrx_t *rx) { /** * @brief 读取当前FIFO中缓存了多少帧的数据 */ CAN_RxHeaderTypeDef pHeader; uint32_t level = HAL_CAN_GetRxFifoFillLevel(&hcan1, FIFO_NUM); if (level == 0) { return false; } HAL_StatusTypeDef HAL_RetVal; HAL_RetVal = HAL_CAN_GetRxMessage(&hcan1, FIFO_NUM, &pHeader, rx->rxpacket); rx->extid = pHeader.ExtId; rx->rkpacketlen = pHeader.DLC; if (HAL_OK == HAL_RetVal) { // 处理接收到的can总线数据 return true; } return false; } static inline const char *zhex2str(uint8_t *data, uint32_t len) { static char str[256]; for (uint32_t i = 0; i < len; i++) { sprintf(str + i * 2, "%02X", data[i]); } return str; } void ZCAN1::STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *canHandle) { if (canHandle != &hcan1) { return; } /** * @brief TODO:临时测试代码 */ while (true) { zcanrx_t rx; bool rxmsg = getRxMsg(&rx); if (rxmsg) { rxQueue.send(&rx, 0); } else { break; } } } void ZCAN1::STM32_HAL_onCAN_Error(CAN_HandleTypeDef *canHandle) { ZLOGE(TAG, "onCAN_Error\r\n"); }