5 changed files with 315 additions and 32 deletions
-
33.cproject
-
2app_protocols
-
254ucomponents/zcan/zcan.cpp
-
46ucomponents/zcan/zcan.hpp
-
12usrc/service/app_core.cpp
@ -1 +1 @@ |
|||
Subproject commit 5f6308f9929809ffe5481b03d32488334f33c0e9 |
|||
Subproject commit 94d89e0e6d4a76e4eb434557974187e73dced518 |
@ -0,0 +1,254 @@ |
|||
#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() { |
|||
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; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
void ZCAN1::regOnCanMessagePending(function<void()> fn) {} |
|||
|
|||
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"); } |
@ -0,0 +1,46 @@ |
|||
#pragma once
|
|||
|
|||
#include "cmsis_os.h"
|
|||
#include "stm32basic/stm32basic.hpp"
|
|||
#include "stm32basic/zqueue.hpp"
|
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
typedef struct { |
|||
uint32_t extid; |
|||
uint8_t rxpacket[8]; |
|||
int32_t rkpacketlen; |
|||
} zcanrx_t; |
|||
|
|||
class ZCAN1 { |
|||
zmutex m_lock = {"ZCAN1"}; |
|||
ZThread canListener; |
|||
|
|||
ZQueue<zcanrx_t> rxQueue; |
|||
|
|||
function<void(zcanrx_t* rx)> onZcanRx; |
|||
|
|||
public: |
|||
ZCAN1() {} |
|||
|
|||
static ZCAN1 *ins() { |
|||
static ZCAN1 instance; |
|||
return &instance; |
|||
} |
|||
|
|||
void init(); |
|||
bool txMsg(const uint32_t extid, const uint8_t txdata[], uint32_t txdatalen, int32_t overtime); |
|||
bool getRxMsg(zcanrx_t *rx); |
|||
void regOnCanMessagePending(function<void()> fn); |
|||
|
|||
public: |
|||
void STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *can); |
|||
void STM32_HAL_onCAN_Error(CAN_HandleTypeDef *can); |
|||
|
|||
private: |
|||
HAL_StatusTypeDef initializeFilter(); |
|||
HAL_StatusTypeDef activateRxIT(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue