From e5b0b1de3f2466d0d81d1145497cf6b2c3a1296b Mon Sep 17 00:00:00 2001 From: zhaohe Date: Thu, 29 Aug 2024 21:28:50 +0800 Subject: [PATCH] update --- .cproject | 33 +----- app_protocols | 2 +- ucomponents/zcan/zcan.cpp | 254 ++++++++++++++++++++++++++++++++++++++++++++++ ucomponents/zcan/zcan.hpp | 46 +++++++++ usrc/service/app_core.cpp | 12 +++ 5 files changed, 315 insertions(+), 32 deletions(-) create mode 100644 ucomponents/zcan/zcan.cpp create mode 100644 ucomponents/zcan/zcan.hpp diff --git a/.cproject b/.cproject index 82f1551..df2143f 100644 --- a/.cproject +++ b/.cproject @@ -120,43 +120,14 @@ - - - - + - + diff --git a/app_protocols b/app_protocols index 5f6308f..94d89e0 160000 --- a/app_protocols +++ b/app_protocols @@ -1 +1 @@ -Subproject commit 5f6308f9929809ffe5481b03d32488334f33c0e9 +Subproject commit 94d89e0e6d4a76e4eb434557974187e73dced518 diff --git a/ucomponents/zcan/zcan.cpp b/ucomponents/zcan/zcan.cpp new file mode 100644 index 0000000..c5f75f0 --- /dev/null +++ b/ucomponents/zcan/zcan.cpp @@ -0,0 +1,254 @@ +#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() { + __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 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"); } diff --git a/ucomponents/zcan/zcan.hpp b/ucomponents/zcan/zcan.hpp new file mode 100644 index 0000000..c484423 --- /dev/null +++ b/ucomponents/zcan/zcan.hpp @@ -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 rxQueue; + + function 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 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 diff --git a/usrc/service/app_core.cpp b/usrc/service/app_core.cpp index 7ba4d78..6728257 100644 --- a/usrc/service/app_core.cpp +++ b/usrc/service/app_core.cpp @@ -9,6 +9,7 @@ #include "service/remote_controler_state_sync_service.hpp" // #include "service/page/page.hpp" +#include "ucomponents/zcan/zcan.hpp" #define TAG "main" using namespace iflytop; @@ -167,6 +168,8 @@ void AppCore::appsetup() { // dim UIS->chpage(pg_login); + ZCAN1::ins()->init(); + osDelay(100); for (size_t i = 0;; i++) { if (i != 0) ZLOGI(TAG, "re start scan %s %d", "AciDisp00000", i); @@ -198,7 +201,16 @@ void AppCore::initialize() { while (true) { osDelay(1); + osDelay(30); + debugLightLoop(); + + valve_ctrl_protocol_t valve_ctrl_msg; + valve_ctrl_msg.valvestate0 = 1; + valve_ctrl_msg.valvestate1 = 2; + valve_ctrl_msg.valvestate2 = 3; + valve_ctrl_msg.valvestate3 = 4; + ZCAN1::ins()->txMsg(kvalve_ctrl_msg, (uint8_t*)&valve_ctrl_msg, sizeof(valve_ctrl_msg), 30); // HAL_IWDG_Refresh(&hiwdg); } }