#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 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(can_tx_message_type) * TX_NUM + 1]; static uint8_t _g_rx_buffer[sizeof(can_rx_message_type) * RX_NUM + 1]; static int shark_send_can0_data(can_tx_message_type *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_rx_message_type 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.extended_id; handle_can_frame(can_id, message.data, message.dlc); return ; } void can_tx_poll(void){ can_tx_message_type can_tr_m; if (CAN1->ests_bit.bof){ shark_can0_reset(); } while (can_get_mailbox((u32)CAN1) != CAN_TX_STATUS_NO_EMPTY) { if (circle_get_data(&g_tx_circle, (uint8_t * )&can_tr_m, sizeof(can_tr_m)) != sizeof(can_tr_m)) { break; } can_message_transmit(CAN1,&can_tr_m); } } static u32 _can_poll_task(void *args) { can_rx_poll(); can_tx_poll(); return 0; } static __inline__ void can_fifo_recv(can_rx_fifo_num_type fifo){ can_rx_message_type Rxmessage; can_message_receive(CAN1, fifo, &Rxmessage); circle_put_data(&g_rx_circle, (uint8_t *)&Rxmessage, sizeof(Rxmessage)); } void USBFS_L_CAN1_RX0_IRQHandler(void) { can_fifo_recv(CAN_RX_FIFO0); } void CAN0_RX1_IRQHandler(void) { can_fifo_recv(CAN_RX_FIFO1); } static void shark_can0_txrx_pin_config(void){ gpio_init_type gpio_init_struct; /* enable can clock */ crm_periph_clock_enable(CAN_PIN_RCU, TRUE); #ifdef CAN_REMAP gpio_pin_remap_config(CAN_REMAP,TRUE); #endif gpio_default_para_init(&gpio_init_struct); /* can tx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = CAN_TX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(CAN_TX_GROUP, &gpio_init_struct); /* can rx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_init_struct.gpio_pins = CAN_RX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_UP; gpio_init(CAN_RX_GROUP, &gpio_init_struct); } static void shark_can0_config(void) { can_base_type can_base_struct; can_baudrate_type can_baudrate_struct; can_filter_init_type can_filter_init_struct; crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, TRUE); /* can base init */ can_default_para_init(&can_base_struct); can_base_struct.mode_selection = CAN_MODE_COMMUNICATE; can_base_struct.ttc_enable = FALSE; can_base_struct.aebo_enable = TRUE; can_base_struct.aed_enable = TRUE; can_base_struct.prsf_enable = FALSE; can_base_struct.mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED; can_base_struct.mmssr_selection = CAN_SENDING_BY_REQUEST; can_base_init(CAN1, &can_base_struct); //CAN0_SPEED==250 //250k bps /* can baudrate, set baudrate = pclk/(baudrate_div *(1 + bts1_size + bts2_size)) */ can_baudrate_struct.baudrate_div = 40; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_5TQ; can_baudrate_struct.bts2_size = CAN_BTS2_4TQ; can_baudrate_set(CAN1, &can_baudrate_struct); /* can filter 0 config */ can_filter_init_struct.filter_activate_enable = TRUE; can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_MASK; can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0; can_filter_init_struct.filter_number = 0; can_filter_init_struct.filter_bit = CAN_FILTER_32BIT; can_filter_init_struct.filter_id_high = (((CAN_MY_ADDRESS << 3) >> 16) & 0xFFFF); /* extended identifier is 29 bit */ can_filter_init_struct.filter_id_low = ((CAN_MY_ADDRESS << 3) & 0xFFFF) | 0x04; can_filter_init_struct.filter_mask_high = ((CAN_FILTER_DEST_MASK << 3) >> 16) & 0xFFFF; /* extended identifier is 29 bit */ can_filter_init_struct.filter_mask_low = ((CAN_FILTER_DEST_MASK << 3) & 0xFFFF) | 0x04; can_filter_init(CAN1, &can_filter_init_struct); // nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0); nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn,CAN_IRQ_PRIORITY,0); /* enable can receive FIFO0 not empty interrupt */ can_interrupt_enable(CAN1, CAN_RF0MIEN_INT, TRUE); } static int shark_send_can0_data(can_tx_message_type *P_message){ can_tx_poll(); if (circle_put_data(&g_tx_circle, (u8 *)P_message, sizeof(can_tx_message_type))){ return CAN_SEND_OK; } return CAN_SEND_ERROR; } static uint8_t can_get_mailbox(uint32_t can_periph) { uint8_t transmit_mailbox = CAN_TX_MAILBOX0; can_type* can_x = CAN1; /* select one empty transmit mailbox */ if(can_x->tsts_bit.tm0ef) { transmit_mailbox = CAN_TX_MAILBOX0; } else if(can_x->tsts_bit.tm1ef) { transmit_mailbox = CAN_TX_MAILBOX1; } else if(can_x->tsts_bit.tm2ef) { transmit_mailbox = CAN_TX_MAILBOX2; } else { transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; } /* return no mailbox empty */ if(CAN_TX_STATUS_NO_EMPTY == transmit_mailbox){ return CAN_TX_STATUS_NO_EMPTY; } return transmit_mailbox; } int shark_can0_send_message(uint32_t can_id, const void*buff, int len){ can_tx_message_type 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.standard_id = 0; trasnmit_msg.extended_id = can_frame_id.id; trasnmit_msg.frame_type = CAN_TFT_DATA; trasnmit_msg.id_type = CAN_ID_EXTENDED; 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){ can_tx_message_type trasnmit_msg; trasnmit_msg.standard_id = 0; trasnmit_msg.extended_id = can_id; trasnmit_msg.frame_type = CAN_TFT_DATA; trasnmit_msg.id_type = CAN_ID_EXTENDED; 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_reset(CAN1); crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, FALSE); } 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(); }