#include #include "os/queue.h" #include "bsp/bsp.h" #include "bsp/can.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 TX_NUM 32 #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(can_trasnmit_message_struct) * TX_NUM + 1]; static uint8_t _g_rx_buffer[sizeof(can_receive_message_struct) * RX_NUM + 1]; static int shark_send_can0_data(can_trasnmit_message_struct *P_message); static uint8_t can_get_mailbox(uint32_t can_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){ can_receive_message_struct 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.rx_efid; handle_can_frame(can_id, message.rx_data, message.rx_dlen); return ; } void can_tx_poll(void){ can_trasnmit_message_struct can_tr_m; while (can_get_mailbox(CAN0) != CAN_NOMAILBOX) { if (circle_get_data(&g_tx_circle, (uint8_t * )&can_tr_m, sizeof(can_tr_m)) != sizeof(can_tr_m)) { break; } can_message_transmit(CAN0,&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){ can_receive_message_struct Rxmessage; can_message_receive(CAN0, fifo, &Rxmessage); circle_put_data(&g_rx_circle, (uint8_t *)&Rxmessage, sizeof(Rxmessage)); } void USBD_LP_CAN0_RX0_IRQHandler(void) { can_fifo_recv(CAN_FIFO0); } void CAN0_RX1_IRQHandler(void) { can_fifo_recv(CAN_FIFO1); } static void shark_can0_txrx_pin_config(void){ /* enable can clock */ rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_AF); //gpio_pin_remap_config(GPIO_CAN_FULL_REMAP,DISABLE); //gpio_pin_remap_config(GPIO_CAN_PARTIAL_REMAP,ENABLE); gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11); } static void shark_can0_config(void) { can_parameter_struct can_parameter; can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); /* initialize CAN register */ can_deinit(CAN0); //can_deinit(CAN1); /* initialize CAN parameters */ can_parameter.time_triggered = DISABLE; can_parameter.auto_bus_off_recovery = ENABLE; can_parameter.auto_wake_up = DISABLE; can_parameter.rec_fifo_overwrite = DISABLE; can_parameter.trans_fifo_order = ENABLE; can_parameter.no_auto_retrans = ENABLE; #if CAN0_SPEED==250 //250k bps if (SystemCoreClock == 120000000) { can_parameter.resync_jump_width = CAN_BT_SJW_1TQ; can_parameter.time_segment_1 = CAN_BT_BS1_5TQ; can_parameter.time_segment_2 = CAN_BT_BS2_4TQ; } else { can_parameter.resync_jump_width = CAN_BT_SJW_1TQ; can_parameter.time_segment_1 = CAN_BT_BS1_5TQ; can_parameter.time_segment_2 = CAN_BT_BS2_3TQ; } #endif can_parameter.working_mode = CAN_NORMAL_MODE; can_parameter.prescaler = 24; /* initialize CAN */ can_init(CAN0, &can_parameter); /* recv my can ID, use fifo0 */ can_filter_mask_mode_init(CAN_MY_ADDRESS, CAN_FILTER_DEST_MASK, CAN_EXTENDED_FIFO0, 0); nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn,2,0); /* enable can receive FIFO0 not empty interrupt */ can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); /* recv broadcast, fifo1 */ can_filter_mask_mode_init(CAN_NODE_ADDR_FF, CAN_FILTER_DEST_MASK, CAN_EXTENDED_FIFO1, 1); /* recv ccu aux fifo2*/ can_filter_mask_mode_init(CAN_NODE_ADDR_CCU_AUX, CAN_FILTER_DEST_MASK, CAN_EXTENDED_FIFO1, 2); /* recv ble fifo3*/ can_filter_mask_mode_init(CAN_NODE_ADDR_BLE, CAN_FILTER_DEST_MASK, CAN_EXTENDED_FIFO1, 3); can_filter_mask_mode_init(CAN_NODE_ADDR_ACU, CAN_FILTER_DEST_MASK, CAN_EXTENDED_FIFO1, 4); nvic_irq_enable(CAN0_RX1_IRQn,10,0); /* enable can receive FIFO1 not empty interrupt */ can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE1); } static int shark_send_can0_data(can_trasnmit_message_struct *P_message){ if (circle_put_data(&g_tx_circle, (u8 *)P_message, sizeof(can_trasnmit_message_struct))){ return CAN_SEND_OK; } return CAN_SEND_ERROR; } static uint8_t can_get_mailbox(uint32_t can_periph) { uint8_t mailbox_number = CAN_MAILBOX0; /* select one empty mailbox */ if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ mailbox_number = CAN_MAILBOX0; }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ mailbox_number = CAN_MAILBOX1; }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ mailbox_number = CAN_MAILBOX2; }else{ mailbox_number = CAN_NOMAILBOX; } /* return no mailbox empty */ if(CAN_NOMAILBOX == mailbox_number){ return CAN_NOMAILBOX; } return mailbox_number; } int shark_can0_send_message(uint32_t can_id, const void*buff, int len){ can_trasnmit_message_struct 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.tx_sfid = 0; trasnmit_msg.tx_efid = can_frame_id.id; trasnmit_msg.tx_ft = CAN_FT_DATA; trasnmit_msg.tx_ff = CAN_FF_EXTENDED; trasnmit_msg.tx_dlen = min(CAN_DATA_SIZE,send_len); memcpy((char *)trasnmit_msg.tx_data, (char *)buff + (len - send_len), trasnmit_msg.tx_dlen); send_len -= trasnmit_msg.tx_dlen; frame_id ++; 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(CAN0); rcu_periph_clock_disable(RCU_CAN0); gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, GPIO_PIN_9); } 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(); }