mirror of https://github.com/commaai/body.git
191 lines
5.3 KiB
C
191 lines
5.3 KiB
C
// Define to prevent recursive inclusion
|
|
#ifndef COMMS_H
|
|
#define COMMS_H
|
|
|
|
#define OFFSET 0x8U
|
|
#define BROADCAST_ADDR 0x7DFU
|
|
#define FALLBACK_ADDR 0x7E0U
|
|
#define FALLBACK_R_ADDR (FALLBACK_ADDR + OFFSET)
|
|
#define ENGINE_ADDR 0x720U
|
|
#define ENGINE_R_ADDR (ENGINE_ADDR + OFFSET)
|
|
#define DEBUG_ADDR 0x721U
|
|
#define DEBUG_R_ADDR (DEBUG_ADDR + OFFSET)
|
|
|
|
#include "drivers/llbxcan.h"
|
|
#include "uds.h"
|
|
|
|
extern P rtP_Left;
|
|
extern P rtP_Right;
|
|
extern volatile int16_t cmdL; // global variable for Left Command
|
|
extern volatile int16_t cmdR; // global variable for Right Command
|
|
extern uint8_t hw_type;
|
|
extern board_t board;
|
|
|
|
extern uint32_t enter_bootloader_mode;
|
|
extern volatile uint32_t torque_cmd_timeout;
|
|
|
|
extern volatile uint32_t ignition_off_counter;
|
|
|
|
const uint8_t crc_poly = 0xD5U; // standard crc8
|
|
uint32_t current_idx = 0;
|
|
|
|
typedef struct {
|
|
volatile uint32_t w_ptr;
|
|
volatile uint32_t r_ptr;
|
|
uint32_t fifo_size;
|
|
CAN_FIFOMailBox_TypeDef *elems;
|
|
} can_ring;
|
|
|
|
#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(tx_q, 0x1A0)
|
|
|
|
bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
|
bool ret = 0;
|
|
|
|
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;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
|
|
bool ret = false;
|
|
uint32_t next_w_ptr;
|
|
|
|
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;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void can_send_msg(uint32_t addr, uint32_t dhr, uint32_t dlr, uint8_t len) {
|
|
CAN_FIFOMailBox_TypeDef to_push;
|
|
|
|
to_push.RDHR = dhr;
|
|
to_push.RDLR = dlr;
|
|
to_push.RDTR = len;
|
|
to_push.RIR = ((addr >= 0x800U) ? ((addr << 3) | (1U << 2)) : (addr << 21)) | 1;
|
|
|
|
can_push(&can_tx_q, &to_push);
|
|
}
|
|
|
|
void process_can(void) {
|
|
__disable_irq();
|
|
CAN_FIFOMailBox_TypeDef to_send;
|
|
if ((board.CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
|
if (can_pop(&can_tx_q, &to_send)) {
|
|
board.CAN->sTxMailBox[0].TDLR = to_send.RDLR;
|
|
board.CAN->sTxMailBox[0].TDHR = to_send.RDHR;
|
|
board.CAN->sTxMailBox[0].TDTR = to_send.RDTR;
|
|
board.CAN->sTxMailBox[0].TIR = to_send.RIR;
|
|
}
|
|
}
|
|
__enable_irq();
|
|
}
|
|
|
|
void can_rx(void) {
|
|
while ((board.CAN->RF0R & CAN_RF0R_FMP0) != 0) {
|
|
uint32_t address = board.CAN->sFIFOMailBox[0].RIR >> 21;
|
|
if (address == (0x250U + board.can_addr_offset)) {
|
|
if ((GET_MAILBOX_BYTES_04(&board.CAN->sFIFOMailBox[0]) == 0xdeadface) && (GET_MAILBOX_BYTES_48(&board.CAN->sFIFOMailBox[0]) == 0x0ab00b1e)) {
|
|
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
|
|
NVIC_SystemReset();
|
|
}
|
|
#define MSG_TRQ_LEN 6
|
|
uint8_t dat[MSG_TRQ_LEN];
|
|
for (int i=0; i<MSG_TRQ_LEN; i++) {
|
|
dat[i] = GET_MAILBOX_BYTE(&board.CAN->sFIFOMailBox[0], i);
|
|
}
|
|
uint16_t valueL = ((dat[0] << 8U) | dat[1]);
|
|
uint16_t valueR = ((dat[2] << 8U) | dat[3]);
|
|
|
|
uint8_t idx = dat[4] & 0xFU;
|
|
if (crc_checksum(dat, 5, crc_poly) == dat[5]) {
|
|
if (((current_idx + 1U) & 0xFU) == idx) {
|
|
cmdL = valueL;
|
|
cmdR = valueR;
|
|
torque_cmd_timeout = 0;
|
|
}
|
|
current_idx = idx;
|
|
}
|
|
out_enable(LED_BLUE, true);
|
|
} else if (address == (0x251U + board.can_addr_offset)) {
|
|
#define MSG_SPD_LEN 5
|
|
uint8_t dat[MSG_TRQ_LEN];
|
|
for (int i=0; i<MSG_TRQ_LEN; i++) {
|
|
dat[i] = GET_MAILBOX_BYTE(&board.CAN->sFIFOMailBox[0], i);
|
|
}
|
|
uint16_t valueL = ((dat[0] << 8U) | dat[1]);
|
|
uint16_t valueR = ((dat[2] << 8U) | dat[3]);
|
|
|
|
if (crc_checksum(dat, 4, crc_poly) == dat[4]) {
|
|
if ((valueL == 0) || (valueR == 0)) {
|
|
rtP_Left.n_max = rtP_Right.n_max = N_MOT_MAX << 4;
|
|
} else {
|
|
rtP_Left.n_max = valueL << 4;
|
|
rtP_Right.n_max = valueR << 4;
|
|
}
|
|
}
|
|
out_enable(LED_BLUE, true);
|
|
} else if ((address == BROADCAST_ADDR) || // Process UBS and OBD2 requests
|
|
(address == FALLBACK_ADDR) ||
|
|
(address == (ENGINE_ADDR + board.uds_offset)) ||
|
|
(address == (DEBUG_ADDR + board.uds_offset))) {
|
|
process_uds(address, GET_MAILBOX_BYTES_04(&board.CAN->sFIFOMailBox[0]));
|
|
out_enable(LED_BLUE, true);
|
|
} else if ((hw_type == HW_TYPE_BASE) && (address == 0x203U + KNEE_ADDR_OFFSET)) { // detect knee by body and set flag for use with UDS message
|
|
knee_detected = 1;
|
|
} else if ((hw_type == HW_TYPE_KNEE) && (address == 0x202U)) { // CAN based ignition for knee
|
|
ignition_off_counter = 0;
|
|
}
|
|
// next
|
|
board.CAN->RF0R |= CAN_RF0R_RFOM0;
|
|
}
|
|
}
|
|
|
|
void CAN1_TX_IRQHandler(void) {
|
|
// clear interrupt
|
|
board.CAN->TSR |= CAN_TSR_RQCP0;
|
|
process_can();
|
|
}
|
|
|
|
void CAN1_SCE_IRQHandler(void) {
|
|
llcan_clear_send(board.CAN);
|
|
}
|
|
|
|
void CAN1_RX0_IRQHandler(void) {
|
|
can_rx();
|
|
}
|
|
|
|
void CAN2_TX_IRQHandler(void) {
|
|
// clear interrupt
|
|
board.CAN->TSR |= CAN_TSR_RQCP0;
|
|
process_can();
|
|
}
|
|
|
|
void CAN2_SCE_IRQHandler(void) {
|
|
llcan_clear_send(board.CAN);
|
|
}
|
|
|
|
void CAN2_RX0_IRQHandler(void) {
|
|
can_rx();
|
|
}
|
|
|
|
#endif
|