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.
 
 

258 lines
8.0 KiB

#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() {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_CAN1_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
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);
// 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::init() {
if (inited) return;
inited = true;
can1_init();
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) {
ZLOGE(TAG, "HAL_CAN_IsTxMessagePending overtime");
HAL_CAN_AbortTxRequest(&hcan1, txMailBox);
return false;
}
osDelay(i);
i++;
}
return true;
}
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"); }