Bounty: panda high quality CAN autobaud (#96)

* CAN auto-baud

* Disable autobaud when exiting silent mode
This commit is contained in:
Greg Hogan 2018-04-11 16:31:48 -05:00 committed by Chris Vickery
parent 6557cd258a
commit 95919b932d
3 changed files with 122 additions and 32 deletions

View File

@ -86,6 +86,7 @@ int can_err_cnt = 0;
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};
bool can_autobaud_enabled[] = {true, true, true, false};
#define CAN_MAX 3
#else
CAN_TypeDef *cans[] = {CAN1, CAN2};
@ -93,10 +94,21 @@ int can_err_cnt = 0;
uint8_t can_num_lookup[] = {1,0};
int8_t can_forwarding[] = {-1,-1};
uint32_t can_speed[] = {5000, 5000};
bool can_autobaud_enabled[] = {true, true};
#define CAN_MAX 2
#endif
uint32_t can_autobaud_speeds[] = {5000, 2500, 1250, 1000, 10000};
#define AUTOBAUD_SPEEDS_LEN (sizeof(can_autobaud_speeds) / sizeof(can_autobaud_speeds[0]))
#define CANIF_FROM_CAN_NUM(num) (cans[num])
#ifdef PANDA
#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"))
#else
#define CAN_NUM_FROM_CANIF(CAN) (CAN==CAN1 ? 0 : 1)
#define CAN_NAME_FROM_CANIF(CAN) (CAN==CAN1 ? "CAN1" : "CAN2")
#endif
#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num])
#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num])
@ -115,43 +127,78 @@ int can_err_cnt = 0;
// 5000 = 500 kbps
#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10 / (x))
void can_autobaud_speed_increment(uint8_t can_number) {
uint32_t autobaud_speed = can_autobaud_speeds[0];
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
for (int i = 0; i < AUTOBAUD_SPEEDS_LEN; i++) {
if (can_speed[bus_number] == can_autobaud_speeds[i]) {
if (i+1 < AUTOBAUD_SPEEDS_LEN) {
autobaud_speed = can_autobaud_speeds[i+1];
}
break;
}
}
can_speed[bus_number] = autobaud_speed;
#ifdef DEBUG
CAN_TypeDef* CAN = CANIF_FROM_CAN_NUM(can_number);
puts(CAN_NAME_FROM_CANIF(CAN));
puts(" auto-baud test ");
putui(can_speed[bus_number]);
puts(" cbps\n");
#endif
}
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);
while (true) {
// initialization mode
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
// set time quanta from defines
CAN->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) |
(CAN_BTR_TS2_0 * (CAN_SEQ2-1)) |
(can_speed_to_prescaler(can_speed[bus_number]) - 1);
// silent loopback mode for debugging
if (can_loopback) {
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
}
if (can_silent & (1 << can_number)) {
CAN->BTR |= CAN_BTR_SILM;
}
// reset
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM;
#define CAN_TIMEOUT 1000000
int tmp = 0;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
if (tmp < CAN_TIMEOUT) {
return;
}
if (can_autobaud_enabled[bus_number]) {
can_autobaud_speed_increment(can_number);
} else {
puts("CAN init FAILED!!!!!\n");
puth(can_number); puts(" ");
puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n");
return;
}
}
}
void can_init(uint8_t can_number) {
if (can_number == 0xff) return;
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
set_can_enable(CAN, 1);
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
// set time quanta from defines
CAN->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) |
(CAN_BTR_TS2_0 * (CAN_SEQ2-1)) |
(can_speed_to_prescaler(can_speed[BUS_NUM_FROM_CAN_NUM(can_number)]) - 1);
// silent loopback mode for debugging
if (can_loopback) {
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
}
if (can_silent & (1 << can_number)) {
CAN->BTR |= CAN_BTR_SILM;
}
// reset
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM;
#define CAN_TIMEOUT 1000000
int tmp = 0;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
if (tmp == CAN_TIMEOUT) {
puts("CAN init FAILED!!!!!\n");
puth(can_number); puts(" ");
puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n");
}
can_set_speed(can_number);
// accept all filter
CAN->FMR |= CAN_FMR_FINIT;
@ -166,7 +213,7 @@ void can_init(uint8_t can_number) {
CAN->FMR &= ~(CAN_FMR_FINIT);
// enable certain CAN interrupts
CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0;
CAN->IER |= CAN_IER_TMEIE | CAN_IER_FMPIE0;
switch (can_number) {
case 0:
@ -244,6 +291,8 @@ void can_set_gmlan(int bus) {
// CAN error
void can_sce(CAN_TypeDef *CAN) {
enter_critical_section();
can_err_cnt += 1;
#ifdef DEBUG
if (CAN==CAN1) puts("CAN1: ");
@ -264,9 +313,19 @@ void can_sce(CAN_TypeDef *CAN) {
puts("\n");
#endif
uint8_t can_number = CAN_NUM_FROM_CANIF(CAN);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
if (can_autobaud_enabled[bus_number] && (CAN->ESR & CAN_ESR_LEC)) {
can_autobaud_speed_increment(can_number);
can_set_speed(can_number);
}
// clear current send
CAN->TSR |= CAN_TSR_ABRQ0;
CAN->MSR &= ~(CAN_MSR_ERRI);
CAN->MSR = CAN->MSR;
exit_critical_section();
}
// ***************************** CAN *****************************
@ -334,6 +393,14 @@ 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) {
if (can_autobaud_enabled[bus_number]) {
can_autobaud_enabled[bus_number] = false;
puts(CAN_NAME_FROM_CANIF(CAN));
puts(" auto-baud ");
putui(can_speed[bus_number]);
puts(" cbps\n");
}
can_rx_cnt += 1;
// can is live
@ -392,7 +459,7 @@ void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
#endif
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
if (safety_tx_hook(to_push)) {
if (safety_tx_hook(to_push) && !can_autobaud_enabled[bus_number]) {
if (bus_number < BUS_MAX) {
// add CAN packet to send queue
// bus number isn't passed through

View File

@ -266,6 +266,17 @@ int puts(const char *a) {
return 0;
}
void putui(uint32_t i) {
char str[11];
uint8_t idx = 10;
str[idx--] = '\0';
do {
str[idx--] = (i % 10) + 0x30;
i /= 10;
} while (i);
puts(str + idx + 1);
}
void puth(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";

View File

@ -281,9 +281,15 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
break;
case SAFETY_ELM327:
can_silent = ALL_CAN_BUT_MAIN_SILENT;
can_autobaud_enabled[0] = false;
break;
default:
can_silent = ALL_CAN_LIVE;
can_autobaud_enabled[0] = false;
can_autobaud_enabled[1] = false;
#ifdef PANDA
can_autobaud_enabled[2] = false;
#endif
break;
}
can_init_all();
@ -303,6 +309,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
// **** 0xde: set can bitrate
case 0xde:
if (setup->b.wValue.w < BUS_MAX) {
can_autobaud_enabled[setup->b.wValue.w] = false;
can_speed[setup->b.wValue.w] = setup->b.wIndex.w;
can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
}
@ -552,6 +559,11 @@ int main() {
__enable_irq();
// if the error interrupt is enabled to quickly when the CAN bus is active
// something bad happens and you can't connect to the device over USB
delay(10000000);
CAN1->IER |= CAN_IER_ERRIE | CAN_IER_LECIE;
// LED should keep on blinking all the time
uint64_t cnt = 0;