You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					449 lines
				
				13 KiB
			
		
		
			
		
	
	
					449 lines
				
				13 KiB
			| 
								 
											6 years ago
										 
									 | 
							
								// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
							 | 
						||
| 
								 | 
							
								//       CAN2_TX, CAN2_RX0, CAN2_SCE
							 | 
						||
| 
								 | 
							
								//       CAN3_TX, CAN3_RX0, CAN3_SCE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								  volatile uint32_t w_ptr;
							 | 
						||
| 
								 | 
							
								  volatile uint32_t r_ptr;
							 | 
						||
| 
								 | 
							
								  uint32_t fifo_size;
							 | 
						||
| 
								 | 
							
								  CAN_FIFOMailBox_TypeDef *elems;
							 | 
						||
| 
								 | 
							
								} can_ring;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								#define CAN_BUS_RET_FLAG 0x80U
							 | 
						||
| 
								 | 
							
								#define CAN_BUS_NUM_MASK 0x7FU
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								#define BUS_MAX 4U
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								uint32_t can_send_errs = 0;
							 | 
						||
| 
								 | 
							
								uint32_t can_fwd_errs = 0;
							 | 
						||
| 
								 | 
							
								uint32_t gmlan_send_errs = 0;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								extern int can_live, pending_can_live;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// must reinit after changing these
							 | 
						||
| 
								 | 
							
								extern int can_loopback, can_silent;
							 | 
						||
| 
								 | 
							
								extern uint32_t can_speed[4];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_set_forwarding(int from, int to);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_init(uint8_t can_number);
							 | 
						||
| 
								 | 
							
								void can_init_all(void);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								// Ignition detected from CAN meessages
							 | 
						||
| 
								 | 
							
								bool ignition_can = false;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								uint32_t ignition_can_cnt = 0U;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								// end API
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define ALL_CAN_SILENT 0xFF
							 | 
						||
| 
								 | 
							
								#define ALL_CAN_LIVE 0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int can_live = 0, pending_can_live = 0, can_loopback = 0, can_silent = ALL_CAN_SILENT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ********************* instantiate queues *********************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define can_buffer(x, size) \
							 | 
						||
| 
								 | 
							
								  CAN_FIFOMailBox_TypeDef elems_##x[size]; \
							 | 
						||
| 
								 | 
							
								  can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = size, .elems = (CAN_FIFOMailBox_TypeDef *)&elems_##x };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								can_buffer(rx_q, 0x1000)
							 | 
						||
| 
								 | 
							
								can_buffer(tx1_q, 0x100)
							 | 
						||
| 
								 | 
							
								can_buffer(tx2_q, 0x100)
							 | 
						||
| 
								 | 
							
								can_buffer(tx3_q, 0x100)
							 | 
						||
| 
								 | 
							
								can_buffer(txgmlan_q, 0x100)
							 | 
						||
| 
								 | 
							
								can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// global CAN stats
							 | 
						||
| 
								 | 
							
								int can_rx_cnt = 0;
							 | 
						||
| 
								 | 
							
								int can_tx_cnt = 0;
							 | 
						||
| 
								 | 
							
								int can_txd_cnt = 0;
							 | 
						||
| 
								 | 
							
								int can_err_cnt = 0;
							 | 
						||
| 
								 | 
							
								int can_overflow_cnt = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ********************* interrupt safe queue *********************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
							 | 
						||
| 
								 | 
							
								  bool ret = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  ENTER_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (q->w_ptr != q->r_ptr) {
							 | 
						||
| 
								 | 
							
								    *elem = q->elems[q->r_ptr];
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    if ((q->r_ptr + 1U) == q->fifo_size) {
							 | 
						||
| 
								 | 
							
								      q->r_ptr = 0;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      q->r_ptr += 1U;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    ret = 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  EXIT_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
							 | 
						||
| 
								 | 
							
								  bool ret = false;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  uint32_t next_w_ptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  ENTER_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if ((q->w_ptr + 1U) == q->fifo_size) {
							 | 
						||
| 
								 | 
							
								    next_w_ptr = 0;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    next_w_ptr = q->w_ptr + 1U;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (next_w_ptr != q->r_ptr) {
							 | 
						||
| 
								 | 
							
								    q->elems[q->w_ptr] = *elem;
							 | 
						||
| 
								 | 
							
								    q->w_ptr = next_w_ptr;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    ret = true;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  EXIT_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (!ret) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    can_overflow_cnt++;
							 | 
						||
| 
								 | 
							
								    #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								      puts("can_push failed!\n");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_clear(can_ring *q) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  ENTER_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  q->w_ptr = 0;
							 | 
						||
| 
								 | 
							
								  q->r_ptr = 0;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  EXIT_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// assign CAN numbering
							 | 
						||
| 
								 | 
							
								// bus num: Can bus number on ODB connector. Sent to/from USB
							 | 
						||
| 
								 | 
							
								//    Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1)
							 | 
						||
| 
								 | 
							
								// cans: Look up MCU can interface from bus number
							 | 
						||
| 
								 | 
							
								// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc);
							 | 
						||
| 
								 | 
							
								// bus_lookup: Translates from 'can number' to 'bus number'.
							 | 
						||
| 
								 | 
							
								// can_num_lookup: Translates from 'bus number' to 'can number'.
							 | 
						||
| 
								 | 
							
								// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Panda:       Bus 0=CAN1   Bus 1=CAN2   Bus 2=CAN3
							 | 
						||
| 
								 | 
							
								CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3};
							 | 
						||
| 
								 | 
							
								uint8_t bus_lookup[] = {0,1,2};
							 | 
						||
| 
								 | 
							
								uint8_t can_num_lookup[] = {0,1,2,-1};
							 | 
						||
| 
								 | 
							
								int8_t can_forwarding[] = {-1,-1,-1,-1};
							 | 
						||
| 
								 | 
							
								uint32_t can_speed[] = {5000, 5000, 5000, 333};
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								#define CAN_MAX 3U
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								#define CANIF_FROM_CAN_NUM(num) (cans[num])
							 | 
						||
| 
								 | 
							
								#define CAN_NUM_FROM_CANIF(CAN) ((CAN)==CAN1 ? 0 : ((CAN) == CAN2 ? 1 : 2))
							 | 
						||
| 
								 | 
							
								#define CAN_NAME_FROM_CANIF(CAN) ((CAN)==CAN1 ? "CAN1" : ((CAN) == CAN2 ? "CAN2" : "CAN3"))
							 | 
						||
| 
								 | 
							
								#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num])
							 | 
						||
| 
								 | 
							
								#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void process_can(uint8_t can_number);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_set_speed(uint8_t can_number) {
							 | 
						||
| 
								 | 
							
								  CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								  uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (!llcan_set_speed(CAN, can_speed[bus_number], can_loopback, (unsigned int)(can_silent) & (1U << can_number))) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    puts("CAN init FAILED!!!!!\n");
							 | 
						||
| 
								 | 
							
								    puth(can_number); puts(" ");
							 | 
						||
| 
								 | 
							
								    puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_init_all(void) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  for (uint8_t i=0U; i < CAN_MAX; i++) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    can_init(i);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void can_flip_buses(uint8_t bus1, uint8_t bus2){
							 | 
						||
| 
								 | 
							
								  bus_lookup[bus1] = bus2;
							 | 
						||
| 
								 | 
							
								  bus_lookup[bus2] = bus1;
							 | 
						||
| 
								 | 
							
								  can_num_lookup[bus1] = bus2;
							 | 
						||
| 
								 | 
							
								  can_num_lookup[bus2] = bus1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// TODO: Cleanup with new abstraction
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void can_set_gmlan(uint8_t bus) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if(board_has_gmlan()){
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    // first, disable GMLAN on prev bus
							 | 
						||
| 
								 | 
							
								    uint8_t prev_bus = can_num_lookup[3];
							 | 
						||
| 
								 | 
							
								    if (bus != prev_bus) {
							 | 
						||
| 
								 | 
							
								      switch (prev_bus) {
							 | 
						||
| 
								 | 
							
								        case 1:
							 | 
						||
| 
								 | 
							
								        case 2:
							 | 
						||
| 
								 | 
							
								          puts("Disable GMLAN on CAN");
							 | 
						||
| 
								 | 
							
								          puth(prev_bus + 1U);
							 | 
						||
| 
								 | 
							
								          puts("\n");
							 | 
						||
| 
								 | 
							
								          current_board->set_can_mode(CAN_MODE_NORMAL);
							 | 
						||
| 
								 | 
							
								          bus_lookup[prev_bus] = prev_bus;
							 | 
						||
| 
								 | 
							
								          can_num_lookup[prev_bus] = prev_bus;
							 | 
						||
| 
								 | 
							
								          can_num_lookup[3] = -1;
							 | 
						||
| 
								 | 
							
								          can_init(prev_bus);
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								          // GMLAN was not set on either BUS 1 or 2
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    // now enable GMLAN on the new bus
							 | 
						||
| 
								 | 
							
								    switch (bus) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								      case 1:
							 | 
						||
| 
								 | 
							
								      case 2:
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        puts("Enable GMLAN on CAN");
							 | 
						||
| 
								 | 
							
								        puth(bus + 1U);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        puts("\n");
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        current_board->set_can_mode((bus == 1U) ? CAN_MODE_GMLAN_CAN2 : CAN_MODE_GMLAN_CAN3);
							 | 
						||
| 
								 | 
							
								        bus_lookup[bus] = 3;
							 | 
						||
| 
								 | 
							
								        can_num_lookup[bus] = -1;
							 | 
						||
| 
								 | 
							
								        can_num_lookup[3] = bus;
							 | 
						||
| 
								 | 
							
								        can_init(bus);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case 0xFF:  //-1 unsigned
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        puts("GMLAN can only be set on CAN2 or CAN3\n");
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    puts("GMLAN not available on black panda\n");
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								}
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								// TODO: remove
							 | 
						||
| 
								 | 
							
								void can_set_obd(uint8_t harness_orientation, bool obd){
							 | 
						||
| 
								 | 
							
								  if(obd){
							 | 
						||
| 
								 | 
							
								    puts("setting CAN2 to be OBD\n");
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    puts("setting CAN2 to be normal\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if(board_has_obd()){
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    if(obd != (bool)(harness_orientation == HARNESS_STATUS_NORMAL)){
							 | 
						||
| 
								 | 
							
								        // B5,B6: disable normal mode
							 | 
						||
| 
								 | 
							
								        set_gpio_mode(GPIOB, 5, MODE_INPUT);
							 | 
						||
| 
								 | 
							
								        set_gpio_mode(GPIOB, 6, MODE_INPUT);
							 | 
						||
| 
								 | 
							
								        // B12,B13: CAN2 mode
							 | 
						||
| 
								 | 
							
								        set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
							 | 
						||
| 
								 | 
							
								        set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        // B5,B6: CAN2 mode
							 | 
						||
| 
								 | 
							
								        set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
							 | 
						||
| 
								 | 
							
								        set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
							 | 
						||
| 
								 | 
							
								        // B12,B13: disable normal mode
							 | 
						||
| 
								 | 
							
								        set_gpio_mode(GPIOB, 12, MODE_INPUT);
							 | 
						||
| 
								 | 
							
								        set_gpio_mode(GPIOB, 13, MODE_INPUT);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    puts("OBD CAN not available on this board\n");
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// CAN error
							 | 
						||
| 
								 | 
							
								void can_sce(CAN_TypeDef *CAN) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  ENTER_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								    if (CAN==CAN1) puts("CAN1:  ");
							 | 
						||
| 
								 | 
							
								    if (CAN==CAN2) puts("CAN2:  ");
							 | 
						||
| 
								 | 
							
								    #ifdef CAN3
							 | 
						||
| 
								 | 
							
								      if (CAN==CAN3) puts("CAN3:  ");
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								    puts("MSR:");
							 | 
						||
| 
								 | 
							
								    puth(CAN->MSR);
							 | 
						||
| 
								 | 
							
								    puts(" TSR:");
							 | 
						||
| 
								 | 
							
								    puth(CAN->TSR);
							 | 
						||
| 
								 | 
							
								    puts(" RF0R:");
							 | 
						||
| 
								 | 
							
								    puth(CAN->RF0R);
							 | 
						||
| 
								 | 
							
								    puts(" RF1R:");
							 | 
						||
| 
								 | 
							
								    puth(CAN->RF1R);
							 | 
						||
| 
								 | 
							
								    puts(" ESR:");
							 | 
						||
| 
								 | 
							
								    puth(CAN->ESR);
							 | 
						||
| 
								 | 
							
								    puts("\n");
							 | 
						||
| 
								 | 
							
								  #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  can_err_cnt += 1;
							 | 
						||
| 
								 | 
							
								  llcan_clear_send(CAN);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  EXIT_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ***************************** CAN *****************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void process_can(uint8_t can_number) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (can_number != 0xffU) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    ENTER_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								    CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								    uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // check for empty mailbox
							 | 
						||
| 
								 | 
							
								    CAN_FIFOMailBox_TypeDef to_send;
							 | 
						||
| 
								 | 
							
								    if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
							 | 
						||
| 
								 | 
							
								      // add successfully transmitted message to my fifo
							 | 
						||
| 
								 | 
							
								      if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
							 | 
						||
| 
								 | 
							
								        can_txd_cnt += 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
							 | 
						||
| 
								 | 
							
								          CAN_FIFOMailBox_TypeDef to_push;
							 | 
						||
| 
								 | 
							
								          to_push.RIR = CAN->sTxMailBox[0].TIR;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								          to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								          to_push.RDLR = CAN->sTxMailBox[0].TDLR;
							 | 
						||
| 
								 | 
							
								          to_push.RDHR = CAN->sTxMailBox[0].TDHR;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								          can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) {
							 | 
						||
| 
								 | 
							
								          #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								            puts("CAN TX ERROR!\n");
							 | 
						||
| 
								 | 
							
								          #endif
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) {
							 | 
						||
| 
								 | 
							
								          #ifdef DEBUG
							 | 
						||
| 
								 | 
							
								            puts("CAN TX ARBITRATION LOST!\n");
							 | 
						||
| 
								 | 
							
								          #endif
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // clear interrupt
							 | 
						||
| 
								 | 
							
								        // careful, this can also be cleared by requesting a transmission
							 | 
						||
| 
								 | 
							
								        CAN->TSR |= CAN_TSR_RQCP0;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (can_pop(can_queues[bus_number], &to_send)) {
							 | 
						||
| 
								 | 
							
								        can_tx_cnt += 1;
							 | 
						||
| 
								 | 
							
								        // only send if we have received a packet
							 | 
						||
| 
								 | 
							
								        CAN->sTxMailBox[0].TDLR = to_send.RDLR;
							 | 
						||
| 
								 | 
							
								        CAN->sTxMailBox[0].TDHR = to_send.RDHR;
							 | 
						||
| 
								 | 
							
								        CAN->sTxMailBox[0].TDTR = to_send.RDTR;
							 | 
						||
| 
								 | 
							
								        CAN->sTxMailBox[0].TIR = to_send.RIR;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    EXIT_CRITICAL();
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void ignition_can_hook(CAN_FIFOMailBox_TypeDef *to_push) {
							 | 
						||
| 
								 | 
							
								  int bus = GET_BUS(to_push);
							 | 
						||
| 
								 | 
							
								  int addr = GET_ADDR(to_push);
							 | 
						||
| 
								 | 
							
								  int len = GET_LEN(to_push);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  ignition_can_cnt = 0U;  // reset counter
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								  if (bus == 0) {
							 | 
						||
| 
								 | 
							
								    // GM exception
							 | 
						||
| 
								 | 
							
								    if ((addr == 0x1F1) && (len == 8)) {
							 | 
						||
| 
								 | 
							
								      //Bit 5 is ignition "on"
							 | 
						||
| 
								 | 
							
								      ignition_can = (GET_BYTE(to_push, 0) & 0x20) != 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Tesla exception
							 | 
						||
| 
								 | 
							
								    if ((addr == 0x348) && (len == 8)) {
							 | 
						||
| 
								 | 
							
								      // GTW_status
							 | 
						||
| 
								 | 
							
								      ignition_can = (GET_BYTE(to_push, 0) & 0x1) != 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Cadillac exception
							 | 
						||
| 
								 | 
							
								    if ((addr == 0x160) && (len == 5)) {
							 | 
						||
| 
								 | 
							
								      // this message isn't all zeros when ignition is on
							 | 
						||
| 
								 | 
							
								      ignition_can = GET_BYTES_04(to_push) != 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								// CAN receive handlers
							 | 
						||
| 
								 | 
							
								// blink blue when we are receiving CAN messages
							 | 
						||
| 
								 | 
							
								void can_rx(uint8_t can_number) {
							 | 
						||
| 
								 | 
							
								  CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								  uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								  while ((CAN->RF0R & CAN_RF0R_FMP0) != 0) {
							 | 
						||
| 
								 | 
							
								    can_rx_cnt += 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // can is live
							 | 
						||
| 
								 | 
							
								    pending_can_live = 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // add to my fifo
							 | 
						||
| 
								 | 
							
								    CAN_FIFOMailBox_TypeDef to_push;
							 | 
						||
| 
								 | 
							
								    to_push.RIR = CAN->sFIFOMailBox[0].RIR;
							 | 
						||
| 
								 | 
							
								    to_push.RDTR = CAN->sFIFOMailBox[0].RDTR;
							 | 
						||
| 
								 | 
							
								    to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
							 | 
						||
| 
								 | 
							
								    to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // modify RDTR for our API
							 | 
						||
| 
								 | 
							
								    to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // forwarding (panda only)
							 | 
						||
| 
								 | 
							
								    int bus_fwd_num = (can_forwarding[bus_number] != -1) ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
							 | 
						||
| 
								 | 
							
								    if (bus_fwd_num != -1) {
							 | 
						||
| 
								 | 
							
								      CAN_FIFOMailBox_TypeDef to_send;
							 | 
						||
| 
								 | 
							
								      to_send.RIR = to_push.RIR | 1; // TXRQ
							 | 
						||
| 
								 | 
							
								      to_send.RDTR = to_push.RDTR;
							 | 
						||
| 
								 | 
							
								      to_send.RDLR = to_push.RDLR;
							 | 
						||
| 
								 | 
							
								      to_send.RDHR = to_push.RDHR;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								      can_send(&to_send, bus_fwd_num, true);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    safety_rx_hook(&to_push);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    ignition_can_hook(&to_push);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    current_board->set_led(LED_BLUE, true);
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								    // next
							 | 
						||
| 
								 | 
							
								    CAN->RF0R |= CAN_RF0R_RFOM0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void CAN1_TX_IRQ_Handler(void) { process_can(0); }
							 | 
						||
| 
								 | 
							
								void CAN1_RX0_IRQ_Handler(void) { can_rx(0); }
							 | 
						||
| 
								 | 
							
								void CAN1_SCE_IRQ_Handler(void) { can_sce(CAN1); }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void CAN2_TX_IRQ_Handler(void) { process_can(1); }
							 | 
						||
| 
								 | 
							
								void CAN2_RX0_IRQ_Handler(void) { can_rx(1); }
							 | 
						||
| 
								 | 
							
								void CAN2_SCE_IRQ_Handler(void) { can_sce(CAN2); }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void CAN3_TX_IRQ_Handler(void) { process_can(2); }
							 | 
						||
| 
								 | 
							
								void CAN3_RX0_IRQ_Handler(void) { can_rx(2); }
							 | 
						||
| 
								 | 
							
								void CAN3_SCE_IRQ_Handler(void) { can_sce(CAN3); }
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook) {
							 | 
						||
| 
								 | 
							
								  if (skip_tx_hook || safety_tx_hook(to_push) != 0) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								    if (bus_number < BUS_MAX) {
							 | 
						||
| 
								 | 
							
								      // add CAN packet to send queue
							 | 
						||
| 
								 | 
							
								      // bus number isn't passed through
							 | 
						||
| 
								 | 
							
								      to_push->RDTR &= 0xF;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								      if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								      } else {
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								        process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void can_set_forwarding(int from, int to) {
							 | 
						||
| 
								 | 
							
								  can_forwarding[from] = to;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											6 years ago
										 
									 | 
							
								void can_init(uint8_t can_number) {
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN2_TX_IRQn, CAN2_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN2_RX0_IRQn, CAN2_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN2_SCE_IRQn, CAN2_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN3_TX_IRQn, CAN3_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN3_RX0_IRQn, CAN3_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
							 | 
						||
| 
								 | 
							
								  REGISTER_INTERRUPT(CAN3_SCE_IRQn, CAN3_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (can_number != 0xffU) {
							 | 
						||
| 
								 | 
							
								    CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
							 | 
						||
| 
								 | 
							
								    can_set_speed(can_number);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    llcan_init(CAN);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // in case there are queued up messages
							 | 
						||
| 
								 | 
							
								    process_can(can_number);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 |