mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-01 03:43:46 +08:00
openpilot v0.8.8 release
This commit is contained in:
@@ -2,163 +2,7 @@
|
||||
// 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;
|
||||
|
||||
#define CAN_BUS_RET_FLAG 0x80U
|
||||
#define CAN_BUS_NUM_MASK 0x7FU
|
||||
|
||||
#define BUS_MAX 4U
|
||||
|
||||
uint32_t can_rx_errs = 0;
|
||||
uint32_t can_send_errs = 0;
|
||||
uint32_t can_fwd_errs = 0;
|
||||
uint32_t gmlan_send_errs = 0;
|
||||
|
||||
extern int can_live;
|
||||
extern int pending_can_live;
|
||||
|
||||
// must reinit after changing these
|
||||
extern int can_loopback;
|
||||
extern int can_silent;
|
||||
extern uint32_t can_speed[4];
|
||||
|
||||
void can_set_forwarding(int from, int to);
|
||||
|
||||
bool can_init(uint8_t can_number);
|
||||
void can_init_all(void);
|
||||
bool can_tx_check_min_slots_free(uint32_t min);
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook);
|
||||
bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
bool ignition_can = false;
|
||||
bool ignition_cadillac = false;
|
||||
uint32_t ignition_can_cnt = 0U;
|
||||
|
||||
// end API
|
||||
|
||||
#define ALL_CAN_SILENT 0xFF
|
||||
#define ALL_CAN_LIVE 0
|
||||
|
||||
int can_live = 0;
|
||||
int pending_can_live = 0;
|
||||
int can_loopback = 0;
|
||||
int 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)
|
||||
// FIXME:
|
||||
// cppcheck-suppress misra-c2012-9.3
|
||||
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;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr != q->r_ptr) {
|
||||
*elem = q->elems[q->r_ptr];
|
||||
if ((q->r_ptr + 1U) == q->fifo_size) {
|
||||
q->r_ptr = 0;
|
||||
} else {
|
||||
q->r_ptr += 1U;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
||||
bool ret = false;
|
||||
uint32_t next_w_ptr;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if ((q->w_ptr + 1U) == q->fifo_size) {
|
||||
next_w_ptr = 0;
|
||||
} else {
|
||||
next_w_ptr = q->w_ptr + 1U;
|
||||
}
|
||||
if (next_w_ptr != q->r_ptr) {
|
||||
q->elems[q->w_ptr] = *elem;
|
||||
q->w_ptr = next_w_ptr;
|
||||
ret = true;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
if (!ret) {
|
||||
can_overflow_cnt++;
|
||||
#ifdef DEBUG
|
||||
puts("can_push failed!\n");
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t can_slots_empty(can_ring *q) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr >= q->r_ptr) {
|
||||
ret = q->fifo_size - 1U - q->w_ptr + q->r_ptr;
|
||||
} else {
|
||||
ret = q->r_ptr - q->w_ptr - 1U;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_clear(can_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
q->w_ptr = 0;
|
||||
q->r_ptr = 0;
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// 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};
|
||||
#define CAN_MAX 3U
|
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num])
|
||||
#define CAN_NUM_FROM_CANIF(CAN) ((CAN)==CAN1 ? 0 : ((CAN) == CAN2 ? 1 : 2))
|
||||
#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);
|
||||
|
||||
bool can_set_speed(uint8_t can_number) {
|
||||
bool ret = true;
|
||||
@@ -169,22 +13,6 @@ bool can_set_speed(uint8_t can_number) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_init_all(void) {
|
||||
bool ret = true;
|
||||
for (uint8_t i=0U; i < CAN_MAX; i++) {
|
||||
can_clear(can_queues[i]);
|
||||
ret &= can_init(i);
|
||||
}
|
||||
UNUSED(ret);
|
||||
}
|
||||
|
||||
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
|
||||
void can_set_gmlan(uint8_t bus) {
|
||||
if(current_board->has_hw_gmlan){
|
||||
@@ -323,34 +151,6 @@ void process_can(uint8_t can_number) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ignition_can_cnt = 0U; // reset counter
|
||||
|
||||
if (bus == 0) {
|
||||
// TODO: verify on all supported GM models that we can reliably detect ignition using only this signal,
|
||||
// since the 0x1F1 signal can briefly go low immediately after ignition
|
||||
if ((addr == 0x160) && (len == 5)) {
|
||||
// this message isn't all zeros when ignition is on
|
||||
ignition_cadillac = GET_BYTES_04(to_push) != 0;
|
||||
}
|
||||
// GM exception
|
||||
if ((addr == 0x1F1) && (len == 8)) {
|
||||
// Bit 5 is ignition "on"
|
||||
bool ignition_gm = ((GET_BYTE(to_push, 0) & 0x20) != 0);
|
||||
ignition_can = ignition_gm || ignition_cadillac;
|
||||
}
|
||||
// Tesla exception
|
||||
if ((addr == 0x348) && (len == 8)) {
|
||||
// GTW_status
|
||||
ignition_can = (GET_BYTE(to_push, 0) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CAN receive handlers
|
||||
// blink blue when we are receiving CAN messages
|
||||
void can_rx(uint8_t can_number) {
|
||||
@@ -406,34 +206,6 @@ 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); }
|
||||
|
||||
bool can_tx_check_min_slots_free(uint32_t min) {
|
||||
return
|
||||
(can_slots_empty(&can_tx1_q) >= min) &&
|
||||
(can_slots_empty(&can_tx2_q) >= min) &&
|
||||
(can_slots_empty(&can_tx3_q) >= min) &&
|
||||
(can_slots_empty(&can_txgmlan_q) >= min);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (bus_number < BUS_MAX) {
|
||||
// add CAN packet to send queue
|
||||
// bus number isn't passed through
|
||||
to_push->RDTR &= 0xF;
|
||||
if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) {
|
||||
gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
|
||||
} else {
|
||||
can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void can_set_forwarding(int from, int to) {
|
||||
can_forwarding[from] = to;
|
||||
}
|
||||
|
||||
bool can_init(uint8_t can_number) {
|
||||
bool ret = false;
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
typedef struct {
|
||||
volatile uint32_t w_ptr;
|
||||
volatile uint32_t r_ptr;
|
||||
uint32_t fifo_size;
|
||||
CAN_FIFOMailBox_TypeDef *elems;
|
||||
} can_ring;
|
||||
|
||||
#define CAN_BUS_RET_FLAG 0x80U
|
||||
#define CAN_BUS_NUM_MASK 0x7FU
|
||||
|
||||
#define BUS_MAX 4U
|
||||
|
||||
uint32_t can_rx_errs = 0;
|
||||
uint32_t can_send_errs = 0;
|
||||
uint32_t can_fwd_errs = 0;
|
||||
uint32_t gmlan_send_errs = 0;
|
||||
|
||||
extern int can_live;
|
||||
extern int pending_can_live;
|
||||
|
||||
// must reinit after changing these
|
||||
extern int can_loopback;
|
||||
extern int can_silent;
|
||||
extern uint32_t can_speed[4];
|
||||
extern uint32_t can_data_speed[3];
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
bool ignition_can = false;
|
||||
bool ignition_cadillac = false;
|
||||
uint32_t ignition_can_cnt = 0U;
|
||||
|
||||
#define ALL_CAN_SILENT 0xFF
|
||||
#define ALL_CAN_LIVE 0
|
||||
|
||||
int can_live = 0;
|
||||
int pending_can_live = 0;
|
||||
int can_loopback = 0;
|
||||
int can_silent = ALL_CAN_SILENT;
|
||||
|
||||
// ******************* functions prototypes *********************
|
||||
bool can_init(uint8_t can_number);
|
||||
void process_can(uint8_t can_number);
|
||||
|
||||
// ********************* 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)
|
||||
// FIXME:
|
||||
// cppcheck-suppress misra-c2012-9.3
|
||||
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;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr != q->r_ptr) {
|
||||
*elem = q->elems[q->r_ptr];
|
||||
if ((q->r_ptr + 1U) == q->fifo_size) {
|
||||
q->r_ptr = 0;
|
||||
} else {
|
||||
q->r_ptr += 1U;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
||||
bool ret = false;
|
||||
uint32_t next_w_ptr;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if ((q->w_ptr + 1U) == q->fifo_size) {
|
||||
next_w_ptr = 0;
|
||||
} else {
|
||||
next_w_ptr = q->w_ptr + 1U;
|
||||
}
|
||||
if (next_w_ptr != q->r_ptr) {
|
||||
q->elems[q->w_ptr] = *elem;
|
||||
q->w_ptr = next_w_ptr;
|
||||
ret = true;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
if (!ret) {
|
||||
can_overflow_cnt++;
|
||||
#ifdef DEBUG
|
||||
puts("can_push failed!\n");
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t can_slots_empty(can_ring *q) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr >= q->r_ptr) {
|
||||
ret = q->fifo_size - 1U - q->w_ptr + q->r_ptr;
|
||||
} else {
|
||||
ret = q->r_ptr - q->w_ptr - 1U;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_clear(can_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
q->w_ptr = 0;
|
||||
q->r_ptr = 0;
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
// Helpers
|
||||
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=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};
|
||||
uint32_t can_data_speed[] = {5000, 5000, 5000}; //For CAN FD with BRS only
|
||||
#define CAN_MAX 3U
|
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num])
|
||||
#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num])
|
||||
#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num])
|
||||
|
||||
void can_init_all(void) {
|
||||
bool ret = true;
|
||||
for (uint8_t i=0U; i < CAN_MAX; i++) {
|
||||
can_clear(can_queues[i]);
|
||||
ret &= can_init(i);
|
||||
}
|
||||
UNUSED(ret);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ignition_can_cnt = 0U; // reset counter
|
||||
|
||||
if (bus == 0) {
|
||||
// TODO: verify on all supported GM models that we can reliably detect ignition using only this signal,
|
||||
// since the 0x1F1 signal can briefly go low immediately after ignition
|
||||
if ((addr == 0x160) && (len == 5)) {
|
||||
// this message isn't all zeros when ignition is on
|
||||
ignition_cadillac = GET_BYTES_04(to_push) != 0;
|
||||
}
|
||||
// GM exception
|
||||
if ((addr == 0x1F1) && (len == 8)) {
|
||||
// Bit 5 is ignition "on"
|
||||
bool ignition_gm = ((GET_BYTE(to_push, 0) & 0x20) != 0);
|
||||
ignition_can = ignition_gm || ignition_cadillac;
|
||||
}
|
||||
// Tesla exception
|
||||
if ((addr == 0x348) && (len == 8)) {
|
||||
// GTW_status
|
||||
ignition_can = (GET_BYTE(to_push, 0) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool can_tx_check_min_slots_free(uint32_t min) {
|
||||
return
|
||||
(can_slots_empty(&can_tx1_q) >= min) &&
|
||||
(can_slots_empty(&can_tx2_q) >= min) &&
|
||||
(can_slots_empty(&can_tx3_q) >= min) &&
|
||||
(can_slots_empty(&can_txgmlan_q) >= min);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (bus_number < BUS_MAX) {
|
||||
// add CAN packet to send queue
|
||||
// bus number isn't passed through
|
||||
to_push->RDTR &= 0xF;
|
||||
if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) {
|
||||
gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
|
||||
} else {
|
||||
can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void can_set_forwarding(int from, int to) {
|
||||
can_forwarding[from] = to;
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
// IRQs: FDCAN1_IT0, FDCAN1_IT1
|
||||
// FDCAN2_IT0, FDCAN2_IT1
|
||||
// FDCAN3_IT0, FDCAN3_IT1
|
||||
|
||||
#define BUS_OFF_FAIL_LIMIT 2U
|
||||
uint8_t bus_off_err[] = {0U, 0U, 0U};
|
||||
|
||||
FDCAN_GlobalTypeDef *cans[] = {FDCAN1, FDCAN2, FDCAN3};
|
||||
|
||||
bool can_set_speed(uint8_t can_number) {
|
||||
bool ret = true;
|
||||
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
ret &= llcan_set_speed(CANx, can_speed[bus_number], can_data_speed[bus_number], can_loopback, (unsigned int)(can_silent) & (1U << can_number));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void can_set_gmlan(uint8_t bus) {
|
||||
UNUSED(bus);
|
||||
puts("GMLAN not available on red panda\n");
|
||||
}
|
||||
|
||||
void cycle_transceiver(uint8_t can_number) {
|
||||
// FDCAN1 = trans 1, FDCAN3 = trans 3, FDCAN2 = trans 2 normal or 4 flipped harness
|
||||
uint8_t transceiver_number = can_number;
|
||||
if (can_number == 2U) {
|
||||
uint8_t flip = (car_harness_status == HARNESS_STATUS_FLIPPED) ? 2U : 0U;
|
||||
transceiver_number += flip;
|
||||
}
|
||||
current_board->enable_can_transceiver(transceiver_number, false);
|
||||
delay(20000);
|
||||
current_board->enable_can_transceiver(transceiver_number, true);
|
||||
bus_off_err[can_number] = 0U;
|
||||
puts("Cycled transceiver number: "); puth(transceiver_number); puts("\n");
|
||||
}
|
||||
|
||||
// ***************************** CAN *****************************
|
||||
void process_can(uint8_t can_number) {
|
||||
if (can_number != 0xffU) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
|
||||
CANx->IR |= FDCAN_IR_TFE; // Clear Tx FIFO Empty flag
|
||||
|
||||
if ((CANx->TXFQS & FDCAN_TXFQS_TFQF) == 0) {
|
||||
CAN_FIFOMailBox_TypeDef to_send;
|
||||
if (can_pop(can_queues[bus_number], &to_send)) {
|
||||
can_tx_cnt += 1;
|
||||
uint32_t TxFIFOSA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET) + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE);
|
||||
uint8_t tx_index = (CANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1F;
|
||||
// only send if we have received a packet
|
||||
CAN_FIFOMailBox_TypeDef *fifo;
|
||||
fifo = (CAN_FIFOMailBox_TypeDef *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE));
|
||||
|
||||
// Convert from "mailbox type"
|
||||
fifo->RIR = ((to_send.RIR & 0x6) << 28) | (to_send.RIR >> 3); // identifier format and frame type | identifier
|
||||
//REDEBUG: enable CAN FD and BRS for test purposes
|
||||
//fifo->RDTR = ((to_send.RDTR & 0xF) << 16) | ((to_send.RDTR) >> 16) | (1U << 21) | (1U << 20); // DLC (length) | timestamp | enable CAN FD | enable BRS
|
||||
fifo->RDTR = ((to_send.RDTR & 0xF) << 16) | ((to_send.RDTR) >> 16); // DLC (length) | timestamp
|
||||
fifo->RDLR = to_send.RDLR;
|
||||
fifo->RDHR = to_send.RDHR;
|
||||
|
||||
CANx->TXBAR = (1UL << tx_index);
|
||||
|
||||
// Send back to USB
|
||||
can_txd_cnt += 1;
|
||||
CAN_FIFOMailBox_TypeDef to_push;
|
||||
to_push.RIR = to_send.RIR;
|
||||
to_push.RDTR = (to_send.RDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
|
||||
to_push.RDLR = to_send.RDLR;
|
||||
to_push.RDHR = to_send.RDHR;
|
||||
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
|
||||
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
|
||||
usb_outep3_resume_if_paused();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recover after Bus-off state
|
||||
if (((CANx->PSR & FDCAN_PSR_BO) != 0) && ((CANx->CCCR & FDCAN_CCCR_INIT) != 0)) {
|
||||
bus_off_err[can_number] += 1U;
|
||||
puts("CAN is in Bus_Off state! Resetting... CAN number: "); puth(can_number); puts("\n");
|
||||
if (bus_off_err[can_number] > BUS_OFF_FAIL_LIMIT) {
|
||||
cycle_transceiver(can_number);
|
||||
}
|
||||
CANx->IR = 0xFFC60000U; // Reset all flags(Only errors!)
|
||||
CANx->CCCR &= ~(FDCAN_CCCR_INIT);
|
||||
uint32_t timeout_counter = 0U;
|
||||
while((CANx->CCCR & FDCAN_CCCR_INIT) != 0) {
|
||||
// Delay for about 1ms
|
||||
delay(10000);
|
||||
timeout_counter++;
|
||||
|
||||
if(timeout_counter >= CAN_INIT_TIMEOUT_MS){
|
||||
puts(CAN_NAME_FROM_CANIF(CANx)); puts(" Bus_Off reset timed out!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
// CAN receive handlers
|
||||
// blink blue when we are receiving CAN messages
|
||||
void can_rx(uint8_t can_number) {
|
||||
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
|
||||
uint8_t rx_fifo_idx;
|
||||
|
||||
// Rx FIFO 0 new message
|
||||
if((CANx->IR & FDCAN_IR_RF0N) != 0) {
|
||||
CANx->IR |= FDCAN_IR_RF0N;
|
||||
while((CANx->RXF0S & FDCAN_RXF0S_F0FL) != 0) {
|
||||
can_rx_cnt += 1;
|
||||
|
||||
// can is live
|
||||
pending_can_live = 1;
|
||||
|
||||
// getting new message index (0 to 63)
|
||||
rx_fifo_idx = (uint8_t)((CANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3F);
|
||||
|
||||
uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET);
|
||||
CAN_FIFOMailBox_TypeDef to_push;
|
||||
CAN_FIFOMailBox_TypeDef *fifo;
|
||||
|
||||
// getting address
|
||||
fifo = (CAN_FIFOMailBox_TypeDef *)(RxFIFO0SA + (rx_fifo_idx * FDCAN_RX_FIFO_0_EL_SIZE));
|
||||
|
||||
// Need to convert real CAN frame format to mailbox "type"
|
||||
to_push.RIR = ((fifo->RIR >> 28) & 0x6) | (fifo->RIR << 3); // identifier format and frame type | identifier
|
||||
to_push.RDTR = ((fifo->RDTR >> 16) & 0xF) | (fifo->RDTR << 16); // DLC (length) | timestamp
|
||||
to_push.RDLR = fifo->RDLR;
|
||||
to_push.RDHR = fifo->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;
|
||||
to_send.RDTR = to_push.RDTR;
|
||||
to_send.RDLR = to_push.RDLR;
|
||||
to_send.RDHR = to_push.RDHR;
|
||||
can_send(&to_send, bus_fwd_num, true);
|
||||
}
|
||||
|
||||
can_rx_errs += safety_rx_hook(&to_push) ? 0U : 1U;
|
||||
ignition_can_hook(&to_push);
|
||||
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
|
||||
// update read index
|
||||
CANx->RXF0A = rx_fifo_idx;
|
||||
}
|
||||
|
||||
} else if((CANx->IR & (FDCAN_IR_PEA | FDCAN_IR_PED | FDCAN_IR_RF0L | FDCAN_IR_RF0F | FDCAN_IR_EW | FDCAN_IR_MRAF | FDCAN_IR_TOO)) != 0) {
|
||||
#ifdef DEBUG
|
||||
puts("FDCAN error, FDCAN_IR: ");puth(CANx->IR);puts("\n");
|
||||
#endif
|
||||
CANx->IR |= (FDCAN_IR_PEA | FDCAN_IR_PED | FDCAN_IR_RF0L | FDCAN_IR_RF0F | FDCAN_IR_EW | FDCAN_IR_MRAF | FDCAN_IR_TOO); // Clean all error flags
|
||||
can_err_cnt += 1;
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); }
|
||||
void FDCAN1_IT1_IRQ_Handler(void) { process_can(0); }
|
||||
|
||||
void FDCAN2_IT0_IRQ_Handler(void) { can_rx(1); }
|
||||
void FDCAN2_IT1_IRQ_Handler(void) { process_can(1); }
|
||||
|
||||
void FDCAN3_IT0_IRQ_Handler(void) { can_rx(2); }
|
||||
void FDCAN3_IT1_IRQ_Handler(void) { process_can(2); }
|
||||
|
||||
bool can_init(uint8_t can_number) {
|
||||
bool ret = false;
|
||||
|
||||
REGISTER_INTERRUPT(FDCAN1_IT0_IRQn, FDCAN1_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(FDCAN1_IT1_IRQn, FDCAN1_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(FDCAN2_IT0_IRQn, FDCAN2_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(FDCAN2_IT1_IRQn, FDCAN2_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(FDCAN3_IT0_IRQn, FDCAN3_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
REGISTER_INTERRUPT(FDCAN3_IT1_IRQn, FDCAN3_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
|
||||
if (can_number != 0xffU) {
|
||||
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
|
||||
ret &= can_set_speed(can_number);
|
||||
ret &= llcan_init(CANx);
|
||||
// in case there are queued up messages
|
||||
process_can(can_number);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -38,6 +38,7 @@ typedef struct uart_ring {
|
||||
// ***************************** Function prototypes *****************************
|
||||
void debug_ring_callback(uart_ring *ring);
|
||||
void uart_tx_ring(uart_ring *q);
|
||||
void uart_send_break(uart_ring *u);
|
||||
|
||||
// ******************************** UART buffers ********************************
|
||||
|
||||
@@ -138,11 +139,6 @@ void uart_flush_sync(uart_ring *q) {
|
||||
}
|
||||
}
|
||||
|
||||
void uart_send_break(uart_ring *u) {
|
||||
while ((u->uart->CR1 & USART_CR1_SBK) != 0);
|
||||
u->uart->CR1 |= USART_CR1_SBK;
|
||||
}
|
||||
|
||||
void clear_uart_buff(uart_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
q->w_ptr_tx = 0;
|
||||
|
||||
@@ -123,7 +123,7 @@ uint8_t device_desc[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size
|
||||
TOUSBORDER(USB_VID), // idVendor
|
||||
TOUSBORDER(USB_PID), // idProduct
|
||||
0x00, 0x23, // bcdDevice
|
||||
0x00, 0x00, // bcdDevice
|
||||
0x01, 0x02, // Manufacturer, Product
|
||||
0x03, 0x01 // Serial Number, Num Configurations
|
||||
};
|
||||
@@ -526,6 +526,8 @@ void usb_setup(void) {
|
||||
case USB_DESC_TYPE_DEVICE:
|
||||
//puts(" writing device descriptor\n");
|
||||
|
||||
// set bcdDevice to hardware type
|
||||
device_desc[13] = hw_type;
|
||||
// setup transfer
|
||||
USB_WritePacket(device_desc, MIN(sizeof(device_desc), setup.b.wLength.w), 0);
|
||||
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
||||
|
||||
Reference in New Issue
Block a user