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);
}
}