mirror of
https://github.com/infiniteCable2/panda.git
synced 2026-02-18 17:23:52 +08:00
* Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
323 lines
7.5 KiB
C
323 lines
7.5 KiB
C
// ********************* Includes *********************
|
|
//#define PEDAL_USB
|
|
#include "../config.h"
|
|
|
|
#include "early_init.h"
|
|
#include "crc.h"
|
|
|
|
#define CAN CAN1
|
|
|
|
#ifdef PEDAL_USB
|
|
#include "drivers/usb.h"
|
|
#else
|
|
// no serial either
|
|
void puts(const char *a) {
|
|
UNUSED(a);
|
|
}
|
|
void puth(unsigned int i) {
|
|
UNUSED(i);
|
|
}
|
|
void puth2(unsigned int i) {
|
|
UNUSED(i);
|
|
}
|
|
#endif
|
|
|
|
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeefU
|
|
uint32_t enter_bootloader_mode;
|
|
|
|
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
|
void __initialize_hardware_early(void) {
|
|
early_initialization();
|
|
}
|
|
|
|
// ********************* serial debugging *********************
|
|
|
|
#ifdef PEDAL_USB
|
|
|
|
void debug_ring_callback(uart_ring *ring) {
|
|
char rcv;
|
|
while (getc(ring, &rcv) != 0) {
|
|
(void)putc(ring, rcv);
|
|
}
|
|
}
|
|
|
|
int usb_cb_ep1_in(void *usbdata, int len, bool hardwired) {
|
|
UNUSED(usbdata);
|
|
UNUSED(len);
|
|
UNUSED(hardwired);
|
|
return 0;
|
|
}
|
|
void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) {
|
|
UNUSED(usbdata);
|
|
UNUSED(len);
|
|
UNUSED(hardwired);
|
|
}
|
|
void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
|
UNUSED(usbdata);
|
|
UNUSED(len);
|
|
UNUSED(hardwired);
|
|
}
|
|
void usb_cb_ep3_out_complete(void) {}
|
|
void usb_cb_enumeration_complete(void) {}
|
|
|
|
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
|
|
UNUSED(hardwired);
|
|
unsigned int resp_len = 0;
|
|
uart_ring *ur = NULL;
|
|
switch (setup->b.bRequest) {
|
|
// **** 0xc1: get hardware type
|
|
case 0xc1:
|
|
resp[0] = hw_type;
|
|
resp_len = 1;
|
|
break;
|
|
// **** 0xe0: uart read
|
|
case 0xe0:
|
|
ur = get_ring_by_number(setup->b.wValue.w);
|
|
if (!ur) {
|
|
break;
|
|
}
|
|
// read
|
|
while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
|
|
getc(ur, (char*)&resp[resp_len])) {
|
|
++resp_len;
|
|
}
|
|
break;
|
|
default:
|
|
puts("NO HANDLER ");
|
|
puth(setup->b.bRequest);
|
|
puts("\n");
|
|
break;
|
|
}
|
|
return resp_len;
|
|
}
|
|
|
|
#endif
|
|
|
|
// ***************************** can port *****************************
|
|
|
|
// addresses to be used on CAN
|
|
#define CAN_GAS_INPUT 0x200
|
|
#define CAN_GAS_OUTPUT 0x201U
|
|
#define CAN_GAS_SIZE 6
|
|
#define COUNTER_CYCLE 0xFU
|
|
|
|
void CAN1_TX_IRQ_Handler(void) {
|
|
// clear interrupt
|
|
CAN->TSR |= CAN_TSR_RQCP0;
|
|
}
|
|
|
|
// two independent values
|
|
uint16_t gas_set_0 = 0;
|
|
uint16_t gas_set_1 = 0;
|
|
|
|
#define MAX_TIMEOUT 10U
|
|
uint32_t timeout = 0;
|
|
uint32_t current_index = 0;
|
|
|
|
#define NO_FAULT 0U
|
|
#define FAULT_BAD_CHECKSUM 1U
|
|
#define FAULT_SEND 2U
|
|
#define FAULT_SCE 3U
|
|
#define FAULT_STARTUP 4U
|
|
#define FAULT_TIMEOUT 5U
|
|
#define FAULT_INVALID 6U
|
|
uint8_t state = FAULT_STARTUP;
|
|
const uint8_t crc_poly = 0xD5U; // standard crc8
|
|
|
|
void CAN1_RX0_IRQ_Handler(void) {
|
|
while ((CAN->RF0R & CAN_RF0R_FMP0) != 0) {
|
|
#ifdef DEBUG
|
|
puts("CAN RX\n");
|
|
#endif
|
|
int address = CAN->sFIFOMailBox[0].RIR >> 21;
|
|
if (address == CAN_GAS_INPUT) {
|
|
// softloader entry
|
|
if (GET_MAILBOX_BYTES_04(&CAN->sFIFOMailBox[0]) == 0xdeadface) {
|
|
if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x0ab00b1e) {
|
|
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
|
|
NVIC_SystemReset();
|
|
} else if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x02b00b1e) {
|
|
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
|
NVIC_SystemReset();
|
|
} else {
|
|
puts("Failed entering Softloader or Bootloader\n");
|
|
}
|
|
}
|
|
|
|
// normal packet
|
|
uint8_t dat[8];
|
|
for (int i=0; i<8; i++) {
|
|
dat[i] = GET_MAILBOX_BYTE(&CAN->sFIFOMailBox[0], i);
|
|
}
|
|
uint16_t value_0 = (dat[0] << 8) | dat[1];
|
|
uint16_t value_1 = (dat[2] << 8) | dat[3];
|
|
bool enable = ((dat[4] >> 7) & 1U) != 0U;
|
|
uint8_t index = dat[4] & COUNTER_CYCLE;
|
|
if (crc_checksum(dat, CAN_GAS_SIZE - 1, crc_poly) == dat[5]) {
|
|
if (((current_index + 1U) & COUNTER_CYCLE) == index) {
|
|
#ifdef DEBUG
|
|
puts("setting gas ");
|
|
puth(value_0);
|
|
puts("\n");
|
|
#endif
|
|
if (enable) {
|
|
gas_set_0 = value_0;
|
|
gas_set_1 = value_1;
|
|
} else {
|
|
// clear the fault state if values are 0
|
|
if ((value_0 == 0U) && (value_1 == 0U)) {
|
|
state = NO_FAULT;
|
|
} else {
|
|
state = FAULT_INVALID;
|
|
}
|
|
gas_set_0 = 0;
|
|
gas_set_1 = 0;
|
|
}
|
|
// clear the timeout
|
|
timeout = 0;
|
|
}
|
|
current_index = index;
|
|
} else {
|
|
// wrong checksum = fault
|
|
state = FAULT_BAD_CHECKSUM;
|
|
}
|
|
}
|
|
// next
|
|
CAN->RF0R |= CAN_RF0R_RFOM0;
|
|
}
|
|
}
|
|
|
|
void CAN1_SCE_IRQ_Handler(void) {
|
|
state = FAULT_SCE;
|
|
llcan_clear_send(CAN);
|
|
}
|
|
|
|
uint32_t pdl0 = 0;
|
|
uint32_t pdl1 = 0;
|
|
unsigned int pkt_idx = 0;
|
|
|
|
int led_value = 0;
|
|
|
|
void TIM3_IRQ_Handler(void) {
|
|
#ifdef DEBUG
|
|
puth(TIM3->CNT);
|
|
puts(" ");
|
|
puth(pdl0);
|
|
puts(" ");
|
|
puth(pdl1);
|
|
puts("\n");
|
|
#endif
|
|
|
|
// check timer for sending the user pedal and clearing the CAN
|
|
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
|
uint8_t dat[8];
|
|
dat[0] = (pdl0 >> 8) & 0xFFU;
|
|
dat[1] = (pdl0 >> 0) & 0xFFU;
|
|
dat[2] = (pdl1 >> 8) & 0xFFU;
|
|
dat[3] = (pdl1 >> 0) & 0xFFU;
|
|
dat[4] = ((state & 0xFU) << 4) | pkt_idx;
|
|
dat[5] = crc_checksum(dat, CAN_GAS_SIZE - 1, crc_poly);
|
|
CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24);
|
|
CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5] << 8);
|
|
CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5
|
|
CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1U;
|
|
++pkt_idx;
|
|
pkt_idx &= COUNTER_CYCLE;
|
|
} else {
|
|
// old can packet hasn't sent!
|
|
state = FAULT_SEND;
|
|
#ifdef DEBUG
|
|
puts("CAN MISS\n");
|
|
#endif
|
|
}
|
|
|
|
// blink the LED
|
|
current_board->set_led(LED_GREEN, led_value);
|
|
led_value = !led_value;
|
|
|
|
TIM3->SR = 0;
|
|
|
|
// up timeout for gas set
|
|
if (timeout == MAX_TIMEOUT) {
|
|
state = FAULT_TIMEOUT;
|
|
} else {
|
|
timeout += 1U;
|
|
}
|
|
}
|
|
|
|
// ***************************** main code *****************************
|
|
|
|
void pedal(void) {
|
|
// read/write
|
|
pdl0 = adc_get(ADCCHAN_ACCEL0);
|
|
pdl1 = adc_get(ADCCHAN_ACCEL1);
|
|
|
|
// write the pedal to the DAC
|
|
if (state == NO_FAULT) {
|
|
dac_set(0, MAX(gas_set_0, pdl0));
|
|
dac_set(1, MAX(gas_set_1, pdl1));
|
|
} else {
|
|
dac_set(0, pdl0);
|
|
dac_set(1, pdl1);
|
|
}
|
|
|
|
watchdog_feed();
|
|
}
|
|
|
|
int main(void) {
|
|
// Init interrupt table
|
|
init_interrupts(true);
|
|
|
|
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)
|
|
|
|
// Should run at around 732Hz (see init below)
|
|
REGISTER_INTERRUPT(TIM3_IRQn, TIM3_IRQ_Handler, 1000U, FAULT_INTERRUPT_RATE_TIM3)
|
|
|
|
disable_interrupts();
|
|
|
|
// init devices
|
|
clock_init();
|
|
peripherals_init();
|
|
detect_external_debug_serial();
|
|
detect_board_type();
|
|
|
|
// init board
|
|
current_board->init();
|
|
|
|
#ifdef PEDAL_USB
|
|
// enable USB
|
|
usb_init();
|
|
#endif
|
|
|
|
// pedal stuff
|
|
dac_init();
|
|
adc_init();
|
|
|
|
// init can
|
|
bool llcan_speed_set = llcan_set_speed(CAN1, 5000, false, false);
|
|
if (!llcan_speed_set) {
|
|
puts("Failed to set llcan speed");
|
|
}
|
|
|
|
bool ret = llcan_init(CAN1);
|
|
UNUSED(ret);
|
|
|
|
// 48mhz / 65536 ~= 732
|
|
timer_init(TIM3, 15);
|
|
NVIC_EnableIRQ(TIM3_IRQn);
|
|
|
|
watchdog_init();
|
|
|
|
puts("**** INTERRUPTS ON ****\n");
|
|
enable_interrupts();
|
|
|
|
// main pedal loop
|
|
while (1) {
|
|
pedal();
|
|
}
|
|
|
|
return 0;
|
|
}
|