#include #include "os/queue.h" #include "bsp/bsp_driver.h" #include "libs/utils.h" #include "libs/circle_buffer.h" #define CAN_RX_MESSAGE_RX_ID 1 #define CAN_SEND_QUEUE_SIZE 32 #define RX_ID_OFFSET 16 #define CAN_SEND_OK 0 #define CAN_SEND_ERROR -1 #define CAN_SEND_WAIT_TIMEOUT -2 #define CAN_DEV CAN1 #define TX_NUM 64 #define RX_NUM 64 static c_buffer_t g_tx_circle; static c_buffer_t g_rx_circle; static uint8_t _g_tx_buffer[sizeof(CanTxMessage) * TX_NUM + 1]; static uint8_t _g_rx_buffer[sizeof(CanRxMessage) * RX_NUM + 1]; static int shark_send_can0_data(CanTxMessage *P_message); static uint8_t can_get_mailbox(CAN_Module *an_periph); /* this function can be overide by app, which need recv the can frame */ __weak void handle_can_frame(can_id_t id, uint8_t *data, int len){ } void can_rx_poll(void){ CanRxMessage message; if (circle_get_data(&g_rx_circle, (uint8_t *)&message, sizeof(message)) != sizeof(message)) { return; } can_id_t can_id; can_id.id = message.ExtId; handle_can_frame(can_id, message.Data , message.DLC); return ; } void can_tx_poll(void){ CanTxMessage can_tr_m; if (CAN_GetFlagSTS(CAN_DEV, CAN_FLAG_BOFFL)){ shark_can0_reset(); } while (can_get_mailbox(CAN_DEV) != CAN_TxSTS_NoMailBox) { if (circle_get_data(&g_tx_circle, (uint8_t * )&can_tr_m, sizeof(can_tr_m)) != sizeof(can_tr_m)) { break; } CAN_TransmitMessage(CAN_DEV,&can_tr_m); } } static u32 _can_poll_task(void *args) { can_rx_poll(); can_tx_poll(); return 0; } static __inline__ void can_fifo_recv(int fifo){ CanRxMessage Rxmessage; CAN_ReceiveMessage(CAN_DEV, fifo, &Rxmessage); circle_put_data(&g_rx_circle, (uint8_t *)&Rxmessage, sizeof(Rxmessage)); } void CAN_RX0_IRQHandler(void) { can_fifo_recv(CAN_FIFO0); } void CAN_RX1_IRQHandler(void) { can_fifo_recv(CAN_FIFO1); } static void shark_can0_txrx_pin_config(void){ /* enable can clock */ rcu_apb1_periph_clock_enable(RCU_CAN0); rcu_apb2_periph_clock_enable(CAN_PIN_RCU); rcu_apb2_periph_clock_enable(RCU_AF); #ifdef CAN_REMAP gpio_pin_remap_config(CAN_REMAP,ENABLE); #endif gpio_init(CAN_TX_GROUP, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CAN_TX_PIN); gpio_init(CAN_RX_GROUP, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, CAN_RX_PIN); } static void can_filter_init(u32 id, u32 mask, u8 fifo, u8 filter) { CAN_FilterInitType CAN_FilterInitStructure; /* CAN filter init */ CAN_FilterInitStructure.Filter_Num = filter; CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode; CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale; CAN_FilterInitStructure.Filter_HighId = (uint16_t)id >> 13; CAN_FilterInitStructure.Filter_LowId = (0x003F8U & (uint16_t)(id << 3)) | (1U << 2); CAN_FilterInitStructure.FilterMask_HighId = (uint16_t)mask >> 13; CAN_FilterInitStructure.FilterMask_LowId = (0x003F8U & (uint16_t)(mask << 3)) | (1U << 2); CAN_FilterInitStructure.Filter_FIFOAssignment = fifo; CAN_FilterInitStructure.Filter_Act = ENABLE; CAN1_InitFilter(&CAN_FilterInitStructure); CAN_INTConfig(CAN_DEV, CAN_INT_FMP0, ENABLE); } static void shark_can0_config(void) { CAN_InitType CAN_InitStructure; /* CAN register init */ CAN_DeInit(CAN_DEV); /* Struct init*/ CAN_InitStruct(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.TTCM = DISABLE; CAN_InitStructure.ABOM = DISABLE; CAN_InitStructure.AWKUM = DISABLE; CAN_InitStructure.NART = ENABLE; CAN_InitStructure.RFLM = DISABLE; CAN_InitStructure.TXFP = ENABLE; CAN_InitStructure.OperatingMode = CAN_Normal_Mode; CAN_InitStructure.RSJW = CAN_RSJW_1tq; CAN_InitStructure.TBS1 = CAN_TBS1_4tq; CAN_InitStructure.TBS2 = CAN_TBS2_3tq; CAN_InitStructure.BaudRatePrescaler = 18; /*Initializes the CAN */ CAN_Init(CAN_DEV, &CAN_InitStructure); /* recv my can ID, use fifo0 */ can_filter_init(CAN_MY_ADDRESS, CAN_FILTER_DEST_MASK, CAN_FIFO0, 0); //nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); nvic_irq_enable(CAN_IRQ0,CAN_IRQ_PRIORITY,0); } static int shark_send_can0_data(CanTxMessage *P_message){ can_tx_poll(); if (circle_put_data(&g_tx_circle, (u8 *)P_message, sizeof(CanTxMessage))){ return CAN_SEND_OK; } return CAN_SEND_ERROR; } static uint8_t can_get_mailbox(CAN_Module *can_periph) { uint8_t transmit_mailbox = 0; /* Check the parameters */ /* Select one empty transmit mailbox */ if ((CAN_DEV->TSTS & CAN_TSTS_TMEM0) == CAN_TSTS_TMEM0) { transmit_mailbox = 0; } else if ((CAN_DEV->TSTS & CAN_TSTS_TMEM1) == CAN_TSTS_TMEM1) { transmit_mailbox = 1; } else if ((CAN_DEV->TSTS & CAN_TSTS_TMEM2) == CAN_TSTS_TMEM2) { transmit_mailbox = 2; } else { transmit_mailbox = CAN_TxSTS_NoMailBox; } return transmit_mailbox; } int shark_can0_send_message(uint32_t can_id, const void*buff, int len){ CanTxMessage trasnmit_msg; can_id_t can_frame_id; u32 total_frames = ((len + 7) >> 3); int send_len = len; u32 frame_id = 1; can_frame_id.id = can_id; can_frame_id.total = total_frames; while(send_len > 0){ can_frame_id.idx = frame_id; trasnmit_msg.StdId = 0; trasnmit_msg.ExtId = can_frame_id.id; trasnmit_msg.RTR = CAN_RTRQ_DATA; trasnmit_msg.IDE = CAN_ID_EXT; trasnmit_msg.DLC = min(CAN_DATA_SIZE,send_len); memcpy((char *)trasnmit_msg.Data, (char *)buff + (len - send_len), trasnmit_msg.DLC); send_len -= trasnmit_msg.DLC; frame_id ++; if (shark_send_can0_data(&trasnmit_msg) != CAN_SEND_OK){ return CAN_SEND_ERROR; } } return CAN_SEND_OK; } int shark_can0_send_ext_message(uint32_t can_id, const void*buff, int len){ CanTxMessage trasnmit_msg; trasnmit_msg.StdId = 0; trasnmit_msg.ExtId = can_id; trasnmit_msg.RTR = CAN_RTRQ_DATA; trasnmit_msg.IDE = CAN_ID_EXT; trasnmit_msg.DLC = min(CAN_DLC_LENGTH,len); memcpy((char *)trasnmit_msg.Data, (char *)buff, trasnmit_msg.DLC); if (shark_send_can0_data(&trasnmit_msg) != CAN_SEND_OK){ return CAN_SEND_ERROR; } return CAN_SEND_OK; } void shark_can0_reset(void){ shark_can0_txrx_pin_config(); shark_can0_config(); } void shark_can0_deinit(void){ CAN_DeInit(CAN_DEV); rcu_apb1_periph_clock_disable(RCU_CAN0); } void shark_can0_init(void){ circle_buffer_init(&g_tx_circle, _g_tx_buffer, sizeof(_g_tx_buffer)); circle_buffer_init(&g_rx_circle, _g_rx_buffer, sizeof(_g_rx_buffer)); shark_task_create(_can_poll_task, NULL); shark_can0_txrx_pin_config(); shark_can0_config(); }