// // Created by zwsd // #pragma once #include #include "basic.hpp" #include "sdk/os/zos.hpp" #include "sdk\components\zprotocols\zcancmder\zcancmder_protocol.hpp" #define ZCAN_SEND_CMD_PREFIX(varcmdid, overtime) \ auto *cmdheader = (Cmdheader_t *)m_txbuf; \ auto *cmd = (varcmdid##_cmd_t *)cmdheader->data; \ cmdheader->cmdid = MODULE_CMDID(varcmdid); \ cmdheader->subcmdid = SUBCMDID(varcmdid); \ cmdheader->packetType = zcr::kpt_cmd; \ static_assert(sizeof(varcmdid##_cmd_t) <= sizeof(m_txbuf), "m_txbuf is too small"); \ cmd->id = m_id; #define ZCAN_SEND_CMD_WITH_STATUS_CB(varcmdid, overtime, ...) \ ZCAN_SEND_CMD_PREFIX(varcmdid, overtime) \ __VA_ARGS__ \ int32_t errorcode = m_cancmder->sendCmdWithStatusCb((uint8_t *)m_txbuf, sizeof(*cmdheader) + sizeof(*cmd), getindexcache(varcmdid), overtime, status_cb); \ return errorcode; #define ZCAN_SEND_CMD(varcmdid, ack, overtime, ...) \ ZCAN_SEND_CMD_PREFIX(varcmdid, overtime) \ __VA_ARGS__ \ int32_t errorcode = m_cancmder->sendCmd((uint8_t *)m_txbuf, sizeof(*cmdheader) + sizeof(*cmd), (uint8_t *)&ack, sizeof(ack), overtime); \ return errorcode; #define ZCAN_SEND_CMD_NO_ACK(varcmdid, overtime, ...) \ ZCAN_SEND_CMD_PREFIX(varcmdid, overtime) \ __VA_ARGS__ \ int32_t errorcode = m_cancmder->sendCmdNoAck((uint8_t *)m_txbuf, sizeof(*cmdheader) + sizeof(*cmd), overtime); \ return errorcode; namespace iflytop { using namespace std; typedef function zcan_commnader_master_onpacket_t; class ZCanCommnaderMasterListener { public: zcan_commnader_master_onpacket_t on_ack; zcan_commnader_master_onpacket_t on_cmd_exec_status_report; zcan_commnader_master_onpacket_t on_report; }; class ZCanCommnaderMaster : public ZCanIRQListener { public: class CFG { public: uint8_t deviceId; // /******************************************************************************* * CANConfig * *******************************************************************************/ CAN_HandleTypeDef *canHandle; // 默认使用CAN1 int canFilterIndex0; // 过滤器0 接收,发给自身的消息 int maxFilterNum; // 使用的过滤器数量,最大值14,默认为7 int rxfifoNum; // 使用的FIFO,默认使用FIFO0 int packetRxOvertime_ms; // }; uint8_t txbuff[2100]; public: class LoopJobContext { public: bool hasDoneSomething; }; private: CFG *m_config = NULL; // 配置 bool m_canOnRxDataFlag = false; // 是否有数据接收,用于从中断上下文转移到MainLoop上下文 uint32_t m_lastPacketTicket = 0; // 上一次接收到消息的时间,用于判断与主机是否断开连接 HAL_StatusTypeDef m_lastTransmitStatus; // 上次调用can发送方法的返回值 #define CAN_PACKET_RX_BUFFER_NUM 5 CanPacketRxBuffer m_canPacketRxBuffer[CAN_PACKET_RX_BUFFER_NUM]; int txPacketInterval_ms = 0; ZThread m_loopThread; map m_on_packet_map; zmutex m_on_packet_map_lock; uint16_t m_index_off = 0; zmutex txlock; public: ZCanCommnaderMaster() {} CFG *createCFG(); void init(CFG *cfg); int32_t sendCmd(uint8_t *packet, size_t len, uint8_t *rxbuf, size_t rxbuflen, int overtime_ms); int32_t sendCmdNoAck(uint8_t *packet, size_t len, int overtime_ms); int32_t sendCmdWithStatusCb(uint8_t *packet, size_t len, uint16_t &packetindex, int overtime_ms, action_cb_status_t status_cb); int32_t sendPacketBlock(uint8_t *packet, size_t len, uint16_t &packetindex, uint8_t *rxbuf, size_t rxbuflen, int overtime_ms, zcan_commnader_master_onpacket_t onReport); void setTxPacketInterval(int interval_ms) { txPacketInterval_ms = interval_ms; } public: virtual void STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *can); virtual void STM32_HAL_onCAN_Error(CAN_HandleTypeDef *can); private: void loop(); uint8_t getDeviceId() { return m_config->deviceId; } void sendPacket(uint8_t *packet, size_t len); void regListener(uint16_t index, // zcan_commnader_master_onpacket_t onack, // zcan_commnader_master_onpacket_t on_cmd_exec_status_report, // zcan_commnader_master_onpacket_t on_report); void unregListener(uint16_t index); void callListener(CanPacketRxBuffer *report); void unregListenerAckCB(uint16_t index); bool isListenerReg(uint16_t index); int getListenerNum(); uint16_t generateFreeIndex(); bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems); HAL_StatusTypeDef initializeFilter(); HAL_StatusTypeDef activateRxIT(); HAL_StatusTypeDef deactivateRxIT(); bool getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/); size_t safe_memcpy(void *dst, size_t dst_max_size, void *src, size_t src_len); void initCanPacketRxBuffer(CanPacketRxBuffer *buf, uint16_t id); CanPacketRxBuffer *allocCanPacketRxBufferInIRQ(uint16_t id); CanPacketRxBuffer *findCanPacketRxBufferInIRQ(uint16_t id); void freeCanPacketRxBuffer(uint16_t id); void processReadyPacket(CanPacketRxBuffer *buf); }; } // namespace iflytop