#include "common.h" #include "drv_can.h" #include "drv_io.h" extern uint8_t work_normal; //********************************************************CAN-START********************************************************** static uint8_t can_rx_ctr_self_buf[CAN_RX_BUF_MAX]; static uint8_t can_rx_ctr_bro_buf[CAN_RX_CTR_BRO_BUF_MAX]; static uint8_t can_rx_test_bro_buf[CAN_RX_TEST_BRO_BUF_MAX]; can_parameter_struct can_parameter; can_filter_parameter_struct can_filter; #define CAN_BAUDRATE 250 uint32_t filter_ctr_self_id = (CTR_ID << 10)|(SELF_ID << 3)|CAN_FF_EXTENDED|CAN_FT_DATA; uint32_t filter_ctr_bro_id = (CTR_ID << 10)|(BROCAST_ID << 3)|CAN_FF_EXTENDED|CAN_FT_DATA; #ifdef CONFIG_CAN_IAP uint32_t filter_test_bro_id = (PRINTF_TER_ID << 10)|(SELF_ID << 3)|CAN_FF_EXTENDED|CAN_FT_DATA; #else uint32_t filter_test_bro_id = (PRINTF_TER_ID << 10)|(BROCAST_ID << 3)|CAN_FF_EXTENDED|CAN_FT_DATA; #endif CAN_FRAME can_ctr_self; CAN_FRAME can_ctr_bro; CAN_FRAME can_test_bro; static shark_can_frame_t shark_can_tx_queue[200]; static shark_u8 shark_can_tx_head; static shark_u8 shark_can_tx_tail; static shark_u16 shark_can_tx_err; static shark_bool shark_can_tx_frame(shark_can_frame_t *frame) { u8 mailbox; if (CAN_TSTAT_TME0 == (CAN_TSTAT(CAN0) & CAN_TSTAT_TME0)) { mailbox = CAN_MAILBOX0; } else if (CAN_TSTAT_TME1 == (CAN_TSTAT(CAN0) & CAN_TSTAT_TME1)) { mailbox = CAN_MAILBOX1; } else if (CAN_TSTAT_TME2 == (CAN_TSTAT(CAN0) & CAN_TSTAT_TME2)) { mailbox = CAN_MAILBOX2; } else { if (work_normal == 0) { return shark_true; } if (shark_can_tx_err < 20000) { shark_can_tx_err++; } else { shark_can_tx_err = 0; can_deinit(CAN0); CAN_Config_HW(); } return shark_false; } shark_can_tx_err = 0; CAN_TMDATA0(CAN0, mailbox) = frame->values[0]; CAN_TMDATA1(CAN0, mailbox) = frame->values[1]; CAN_TMP(CAN0, mailbox) &= ~CAN_TMP_DLENC; CAN_TMP(CAN0, mailbox) |= frame->efid.length + 1; CAN_TMI(CAN0, mailbox) = frame->efid.value << 3 | CAN_FF_EXTENDED | CAN_FT_DATA | CAN_TMI_TEN; return shark_true; } void shark_can_tx_flush(void) { while (shark_can_tx_head != shark_can_tx_tail && shark_can_tx_frame(shark_can_tx_queue + shark_can_tx_head)) { shark_can_tx_head = (shark_can_tx_head + 1) % NELEM(shark_can_tx_queue); } } shark_bool shark_can_send_frame(shark_can_efid_t efid, const void *buff, u8 length) { u8 tail = (shark_can_tx_tail + 1) % NELEM(shark_can_tx_queue); shark_can_frame_t *frame; shark_can_tx_flush(); if (tail == shark_can_tx_head || work_normal == 0) { return shark_false; } frame = shark_can_tx_queue + shark_can_tx_tail; memcpy(frame->data, buff, length); frame->efid.value = efid.value; if (shark_can_tx_tail == shark_can_tx_head && shark_can_tx_frame(frame)) { return shark_true; } shark_can_tx_tail = tail; return shark_true; } shark_bool shark_can_send(u8 dest, u8 src, u8 type, const u8 *buff, u16 length) { shark_can_efid_t efid; u8 index = 1; efid.dest = dest; efid.src = src; efid.type = type; efid.priority = 6; efid.total = (length + 7) / 8; while (length > 0) { u8 wrlen = length < 8 ? length : 8; efid.index = index; efid.length = wrlen - 1; if (shark_can_send_frame(efid, buff, wrlen)) { length -= wrlen; buff += wrlen; index++; } else { return shark_false; } } return shark_true; } void Can_Stop_Send(void) { shark_can_tx_head = shark_can_tx_tail = 0; } int8_t Send_Data_Can(CAN_FRAME*app_can_frame,uint8_t from) { return shark_can_send(app_can_frame->head.dest, app_can_frame->head.sour, app_can_frame->head.rsp, app_can_frame->data, app_can_frame->len); } void Check_Can_Poll(void) { if(work_normal) { if(can_error_get(CAN0) != CAN_ERROR_NONE) { Can_Power_Enable(0); can_deinit(CAN0); CAN_Config_HW(); Can_Power_Enable(1); } } } static void Reset_Can_Rx_Buffer(CAN_FRAME*can_frame) { if(can_frame == NULL) return; memset(&can_frame->head,0x00,sizeof(can_frame->head)); can_frame->len = 0; } uint16_t Get_Data_Can(CAN_FRAME*app_can_frame) { CAN_FRAME* cf_temp = NULL; if(app_can_frame == NULL) return 0; if(get_index_total_value(can_ctr_self.head.index) != 0 && can_ctr_self.head.index == can_ctr_self.head.total&&can_ctr_self.len) cf_temp = &can_ctr_self; else if(get_index_total_value(can_ctr_bro.head.index) != 0 && can_ctr_bro.head.index == can_ctr_bro.head.total&&can_ctr_bro.len) cf_temp = &can_ctr_bro; else if(get_index_total_value(can_test_bro.head.index) != 0 && can_test_bro.head.index == can_test_bro.head.total&&can_test_bro.len) cf_temp = &can_test_bro; if(cf_temp == NULL) return 0; memcpy(&app_can_frame->head,&cf_temp->head,sizeof(cf_temp->head)); memcpy(app_can_frame->data,cf_temp->data,cf_temp->len); app_can_frame->len = cf_temp->len; Reset_Can_Rx_Buffer(cf_temp); return app_can_frame->len; } static void Can_NVIC_Config(void) { // nvic_irq_enable(USBD_HP_CAN0_TX_IRQn,3,0); nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn,3,0); } /** * @brief Configures the CAN. * @param None * @retval None */ void CAN_Config_HW(void) { /* enable CAN clock */ rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); /* configure CAN0 GPIO */ gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_8); gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9); gpio_pin_remap_config(GPIO_CAN_PARTIAL_REMAP,ENABLE); rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_7); Silent_Enable(0); can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_struct_para_init(CAN_INIT_STRUCT, &can_filter); /* initialize CAN register */ can_deinit(CAN0); /* initialize CAN parameters */ can_parameter.time_triggered = DISABLE; can_parameter.auto_bus_off_recovery = DISABLE; can_parameter.auto_wake_up = DISABLE; can_parameter.auto_retrans = DISABLE; can_parameter.rec_fifo_overwrite = DISABLE; can_parameter.trans_fifo_order = ENABLE; can_parameter.working_mode = CAN_NORMAL_MODE; 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; /* 1MBps */ #if CAN_BAUDRATE == 1000 can_parameter.prescaler = 6; /* 500KBps */ #elif CAN_BAUDRATE == 500 can_parameter.prescaler = 12; /* 250KBps */ #elif CAN_BAUDRATE == 250 can_parameter.prescaler = 24; /* 125KBps */ #elif CAN_BAUDRATE == 125 can_parameter.prescaler = 48; /* 100KBps */ #elif CAN_BAUDRATE == 100 can_parameter.prescaler = 60; /* 50KBps */ #elif CAN_BAUDRATE == 50 can_parameter.prescaler = 120; /* 20KBps */ #elif CAN_BAUDRATE == 20 can_parameter.prescaler = 300; #else #error "please select list can baudrate in private defines in drv_can.c " #endif /* initialize CAN */ can_init(CAN0, &can_parameter); /* initialize filter */ can_filter.filter_number=0; can_filter.filter_mode = CAN_FILTERMODE_MASK; can_filter.filter_bits = CAN_FILTERBITS_32BIT; #if 1 can_filter.filter_list_high = (uint16_t)(filter_ctr_self_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_ctr_self_id >> 0); can_filter.filter_mask_high = 0x0001; can_filter.filter_mask_low = 0xFFFF; #else can_filter.filter_list_high = 0x0000; can_filter.filter_list_low = 0x0000; can_filter.filter_mask_high = 0x0000; can_filter.filter_mask_low = 0x0000; #endif can_filter.filter_fifo_number = CAN_FIFO0; can_filter.filter_enable = ENABLE; can_filter_init(&can_filter); /* CAN1 filter number */ #if 1 can_filter.filter_number = 1; can_filter.filter_list_high = (uint16_t)(filter_ctr_bro_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_ctr_bro_id >> 0); can_filter_init(&can_filter); can_filter.filter_number = 2; can_filter.filter_list_high = (uint16_t)(filter_test_bro_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_test_bro_id >> 0); can_filter_init(&can_filter); #endif Can_NVIC_Config(); can_interrupt_enable(CAN0, CAN_INT_RFNE0); } /** * @brief Configures the CAN. * @param None * @retval None */ void CAN_Config(void) { memcpy(&can_ctr_self.head,&filter_ctr_self_id,sizeof(filter_ctr_self_id)); memcpy(&can_ctr_bro.head,&filter_ctr_bro_id,sizeof(filter_ctr_bro_id)); memcpy(&can_test_bro.head,&filter_test_bro_id,sizeof(filter_test_bro_id)); can_ctr_self.data = can_rx_ctr_self_buf; can_ctr_bro.data = can_rx_ctr_bro_buf; can_test_bro.data = can_rx_test_bro_buf; /* enable CAN clock */ rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); /* configure CAN0 GPIO */ gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_8); gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9); gpio_pin_remap_config(GPIO_CAN_PARTIAL_REMAP,ENABLE); rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_7); //Silent_Enable(1); Silent_Enable(0); can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_struct_para_init(CAN_INIT_STRUCT, &can_filter); /* initialize CAN register */ can_deinit(CAN0); /* initialize CAN parameters */ can_parameter.time_triggered = DISABLE; can_parameter.auto_bus_off_recovery = DISABLE; can_parameter.auto_wake_up = DISABLE; can_parameter.auto_retrans = DISABLE; can_parameter.rec_fifo_overwrite = DISABLE; can_parameter.trans_fifo_order = ENABLE; can_parameter.working_mode = CAN_NORMAL_MODE; 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; /* 1MBps */ #if CAN_BAUDRATE == 1000 can_parameter.prescaler = 6; /* 500KBps */ #elif CAN_BAUDRATE == 500 can_parameter.prescaler = 12; /* 250KBps */ #elif CAN_BAUDRATE == 250 can_parameter.prescaler = 24; /* 125KBps */ #elif CAN_BAUDRATE == 125 can_parameter.prescaler = 48; /* 100KBps */ #elif CAN_BAUDRATE == 100 can_parameter.prescaler = 60; /* 50KBps */ #elif CAN_BAUDRATE == 50 can_parameter.prescaler = 120; /* 20KBps */ #elif CAN_BAUDRATE == 20 can_parameter.prescaler = 300; #else #error "please select list can baudrate in private defines in drv_can.c " #endif /* initialize CAN */ can_init(CAN0, &can_parameter); /* initialize filter */ can_filter.filter_number=0; can_filter.filter_mode = CAN_FILTERMODE_MASK; can_filter.filter_bits = CAN_FILTERBITS_32BIT; #if 1 can_filter.filter_list_high = (uint16_t)(filter_ctr_self_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_ctr_self_id >> 0); can_filter.filter_mask_high = 0x0001; can_filter.filter_mask_low = 0xFFFF; #else can_filter.filter_list_high = 0x0000; can_filter.filter_list_low = 0x0000; can_filter.filter_mask_high = 0x0000; can_filter.filter_mask_low = 0x0000; #endif can_filter.filter_fifo_number = CAN_FIFO0; can_filter.filter_enable = ENABLE; can_filter_init(&can_filter); /* CAN1 filter number */ #if 1 can_filter.filter_number = 1; can_filter.filter_list_high = (uint16_t)(filter_ctr_bro_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_ctr_bro_id >> 0); can_filter_init(&can_filter); can_filter.filter_number = 2; can_filter.filter_list_high = (uint16_t)(filter_test_bro_id >> 16); can_filter.filter_list_low = (uint16_t)(filter_test_bro_id >> 0); can_filter_init(&can_filter); #endif Can_NVIC_Config(); can_interrupt_enable(CAN0, CAN_INT_RFNE0); } void USBD_LP_CAN0_RX0_IRQHandler(void) { can_receive_message_struct Rxmessage; CAN_FRAME* cf_temp; uint32_t head,buf_max; can_message_receive(CAN0, CAN_FIFO0, &Rxmessage); switch(Rxmessage.rx_fi) { case 0: cf_temp = &can_ctr_self; buf_max = sizeof(can_rx_ctr_self_buf); break; case 1: cf_temp = &can_ctr_bro; buf_max = sizeof(can_rx_ctr_bro_buf); break; case 2: cf_temp = &can_test_bro; buf_max = sizeof(can_rx_test_bro_buf); break; default:return; } head = (Rxmessage.rx_efid << 3)|(Rxmessage.rx_ff)|(Rxmessage.rx_ft); memcpy(&cf_temp->head,&head,sizeof(head)); if(get_index_total_value(cf_temp->head.index) > get_index_total_value(cf_temp->head.total)) return; head = get_index_total_value(cf_temp->head.total)*8UL; if(head > buf_max) return; head = get_index_total_value(cf_temp->head.index) - 1; memcpy(&cf_temp->data[head<<3],Rxmessage.rx_data,Rxmessage.rx_dlen); if(get_index_total_value(cf_temp->head.index) == get_index_total_value(cf_temp->head.total)) { cf_temp->len = (head << 3) + Rxmessage.rx_dlen; //g_event |= EVENT_CAN_RECEIVE_FINISH; } } static u8 shark_can_log_buff[8]; static u8 shark_can_log_length; // //用于系统调用printf // int fputc(int ch, FILE *f) { if (ch == '\n') { if (shark_can_log_length > 0) { shark_can_send(0x72, 0x42, 3, shark_can_log_buff, shark_can_log_length); shark_can_log_length = 0; } } else if (shark_can_log_length < sizeof(shark_can_log_buff)) { shark_can_log_buff[shark_can_log_length] = ch; shark_can_log_length++; } else { shark_can_send(0x70, 0x42, 3, shark_can_log_buff, shark_can_log_length); shark_can_log_buff[0] = ch; shark_can_log_length = 1; } return ch; } //********************************************************CAN-END**********************************************************