|
|
#include "zcan.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<void(zcanrx_t *rx)> 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"); }
|