Can bus numbers now sequential (0,1,2 not 0,1,4).

Can bus numbers are 7 bit numbers with the 8th bit marking receipt busses (0x80,0x81,0x82 not 2,3,6).
This commit is contained in:
Jessy Diamond Exum
2017-07-14 12:30:34 -07:00
parent 0dc8d4607b
commit c98739b66e
4 changed files with 104 additions and 116 deletions

View File

@@ -1,4 +1,5 @@
void can_init(CAN_TypeDef *CAN, int silent) {
void can_init(uint8_t bus_number, int silent) {
CAN_TypeDef *CAN = CANIF_FROM_BUS_NUM(bus_number);
set_can_enable(CAN, 1);
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;

View File

@@ -5,17 +5,37 @@
// 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.
// old: CAN1 = 1 CAN2 = 0
// panda: CAN1 = 0 CAN2 = 1 CAN3 = 4
#ifdef PANDA
int can_numbering[] = {0,1,4};
CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3};
uint8_t bus_lookup[] = {0,1,2};
uint8_t can_num_lookup[] = {0,1,2}; //bus num -> can num
int8_t can_forwarding[] = {-1, -1, -1};
#define CAN_MAX 3
#else
int can_numbering[] = {1,0,-1};
CAN_TypeDef *cans[] = {CAN2, CAN1};
uint8_t bus_lookup[] = {1,0};
uint8_t can_num_lookup[] = {1,0}; //bus num -> can num
int8_t can_forwarding[] = {-1,-1};
#define CAN_MAX 2
#endif
// can forwards FROM -> TO
#define CAN_MAX 3
int can_forwarding[] = {-1,-1,-1};
#define CANIF_FROM_CAN_NUM(num) (cans[bus_lookup[num]])
#define CANIF_FROM_BUS_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])
#define CAN_BUS_RET_FLAG 0x80
#define CAN_BUS_NUM_MASK 0x7F
// *** end config ***
@@ -55,6 +75,8 @@ can_buffer(tx1_q, 0x100)
can_buffer(tx2_q, 0x100)
can_buffer(tx3_q, 0x100)
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q};
// ********************* interrupt safe queue *********************
int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
@@ -324,7 +346,9 @@ int safety_tx_lin_hook(int lin_num, uint8_t *data, int len, int hardwired);
// ***************************** CAN *****************************
void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
void process_can(uint8_t can_number) {
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
#ifdef DEBUG
puts("process CAN TX\n");
#endif
@@ -333,7 +357,7 @@ void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sTxMailBox[0].TIR;
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((can_number+2) << 4);
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
push(&can_rx_q, &to_push);
@@ -342,7 +366,7 @@ void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
// check for empty mailbox
CAN_FIFOMailBox_TypeDef to_send;
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
if (pop(can_q, &to_send)) {
if (pop(can_queues[bus_number], &to_send)) {
// only send if we have received a packet
CAN->sTxMailBox[0].TDLR = to_send.RDLR;
CAN->sTxMailBox[0].TDHR = to_send.RDHR;
@@ -359,25 +383,24 @@ void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
void CAN1_TX_IRQHandler() {
process_can(CAN1, &can_tx1_q, can_numbering[0]);
process_can(0);
}
void CAN2_TX_IRQHandler() {
process_can(CAN2, &can_tx2_q, can_numbering[1]);
process_can(1);
}
#ifdef CAN3
void CAN3_TX_IRQHandler() {
process_can(CAN3, &can_tx3_q, can_numbering[2]);
process_can(2);
}
#endif
void send_can(CAN_FIFOMailBox_TypeDef *to_push, int flags);
void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number);
// CAN receive handlers
// blink blue when we are receiving CAN messages
void can_rx(CAN_TypeDef *CAN, int can_index) {
int can_number = can_numbering[can_index];
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) {
// can is live
pending_can_live = 1;
@@ -391,18 +414,18 @@ void can_rx(CAN_TypeDef *CAN, int can_index) {
// forwarding (panda only)
#ifdef PANDA
if (can_forwarding[can_index] != -1 && can_numbering[can_forwarding[can_index]] != -1) {
if (can_forwarding[bus_number] != -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;
send_can(&to_send, can_numbering[can_forwarding[can_index]]);
send_can(&to_send, can_forwarding[bus_number]);
}
#endif
// modify RDTR for our API
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (can_number << 4);
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
safety_rx_hook(&to_push);
@@ -419,22 +442,20 @@ void can_rx(CAN_TypeDef *CAN, int can_index) {
void CAN1_RX0_IRQHandler() {
//puts("CANRX1");
//delay(10000);
can_rx(CAN1, 0);
can_rx(0);
}
void CAN2_RX0_IRQHandler() {
//puts("CANRX0");
//delay(10000);
can_rx(CAN2, 1);
can_rx(1);
}
#ifdef CAN3
void CAN3_RX0_IRQHandler() {
//puts("CANRX0");
//delay(10000);
can_rx(CAN3, 2);
can_rx(2);
}
#endif
void CAN1_SCE_IRQHandler() {
//puts("CAN1_SCE\n");
@@ -511,40 +532,12 @@ void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {
}
}
void send_can(CAN_FIFOMailBox_TypeDef *to_push, int flags) {
int i;
CAN_TypeDef *CAN;
can_ring *can_q;
if (flags == can_numbering[0]) {
CAN = CAN1;
can_q = &can_tx1_q;
} else if (flags == can_numbering[1]) {
CAN = CAN2;
can_q = &can_tx2_q;
#ifdef CAN3
} else if (flags == can_numbering[2]) {
CAN = CAN3;
can_q = &can_tx3_q;
#endif
} else if (flags == 8 || flags == 9) {
// fake LIN as CAN
uart_ring *lin_ring = (flags == 8) ? &lin1_ring : &lin2_ring;
for (i = 0; i < min(8, to_push->RDTR & 0xF); i++) {
putc(lin_ring, ((uint8_t*)&to_push->RDLR)[i]);
}
return;
} else {
// no crash
return;
}
void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
// add CAN packet to send queue
// bus number isn't passed through
to_push->RDTR &= 0xF;
push(can_q, to_push);
// flags = can_number
process_can(CAN, can_q, flags);
push(can_queues[bus_number], to_push);
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
}
// send on CAN
@@ -560,9 +553,9 @@ void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {
to_push.RDTR = tf[1];
to_push.RIR = tf[0];
int flags = (to_push.RDTR >> 4) & 0xF;
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK;
if (safety_tx_hook(&to_push, hardwired)) {
send_can(&to_push, flags);
send_can(&to_push, bus_number);
}
}
}
@@ -641,29 +634,28 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
}
break;
case 0xdb: // toggle GMLAN
if (setup->b.wIndex.w == 3) {
if (setup->b.wIndex.w == 1) {
set_can_mode(3, 0); // TODO: Make set_can_mode bus num 'sane' as well.
set_can_mode(2, setup->b.wValue.w);
} else if (setup->b.wIndex.w == 2) {
set_can_mode(2, 0);
set_can_mode(3, setup->b.wValue.w);
} else {
set_can_mode(3, 0);
set_can_mode(2, setup->b.wValue.w);
}
break;
case 0xdc: // set controls allowed
controls_allowed = setup->b.wValue.w == 0x1337;
// take CAN out of SILM, careful with speed!
can_init(CAN1, 0);
can_init(CAN2, 0);
#ifdef CAN3
can_init(CAN3, 0);
#endif
for(i=0; i < CAN_MAX; i++)
can_init(i, 0);
break;
case 0xdd: // enable can forwarding
if (setup->b.wValue.w != 0 && setup->b.wValue.w <= CAN_MAX) {
// 0 sets it to -1
if (setup->b.wIndex.w <= CAN_MAX) {
can_forwarding[setup->b.wValue.w-1] = setup->b.wIndex.w-1;
}
//wValue = Can Bus Num to forward from
//wIndex = Can Bus Num to forward to
if (setup->b.wValue.w < CAN_MAX && setup->b.wIndex.w < CAN_MAX &&
setup->b.wValue.w != setup->b.wIndex.w) { //Set forwarding
can_forwarding[setup->b.wValue.w] = setup->b.wIndex.w & CAN_BUS_NUM_MASK;
}else if(setup->b.wValue.w < CAN_MAX && setup->b.wIndex.w == 0xFF){ //Clear Forwarding
can_forwarding[setup->b.wValue.w] = -1;
}
break;
case 0xe0: // uart read
@@ -848,6 +840,8 @@ void __initialize_hardware_early() {
}
int main() {
int i;
// init devices
clock_init();
periph_init();
@@ -875,19 +869,12 @@ int main() {
usb_init();
// default to silent mode to prevent issues with Ford
#ifdef PANDA_SAFETY
can_init(CAN1, 1);
can_init(CAN2, 1);
#ifdef CAN3
can_init(CAN3, 1);
#endif
#else
can_init(CAN1, 0);
can_init(CAN2, 0);
#ifdef CAN3
can_init(CAN3, 0);
#endif
#endif
for(i=0; i < CAN_MAX; i++)
#ifdef PANDA_SAFETY
can_init(i, 1);
#else
can_init(i, 0);
#endif
adc_init();

View File

@@ -24,7 +24,7 @@ def parse_can_buffer(dat):
address = f1 >> 3
else:
address = f1 >> 21
ret.append((address, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&0xf))
ret.append((address, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&0xFF))
return ret
class PandaWifiStreaming(object):
@@ -81,6 +81,7 @@ class Panda(object):
REQUEST_TYPE = usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE
def __init__(self, serial=None, claim=True):
self._serial = serial
if serial == "WIFI":
self._handle = WifiHandle()
print("opening WIFI device")
@@ -95,7 +96,7 @@ class Panda(object):
self._handle = device.open()
if claim:
self._handle.claimInterface(0)
self._handle.setInterfaceAltSetting(0, 0)
#self._handle.setInterfaceAltSetting(0, 0) #Issue in USB stack
break
assert self._handle != None
@@ -150,7 +151,7 @@ class Panda(object):
self._handle.controlWrite(Panda.REQUEST_TYPE, 0xdc, (0x1337 if on else 0), 0, b'')
def set_gmlan(self, on, bus=2):
self._handle.controlWrite(Panda.REQUEST_TYPE, 0xdb, 1, bus, b'')
self._handle.controlWrite(Panda.REQUEST_TYPE, 0xdb, on, bus, b'')
def set_uart_baud(self, uart, rate):
self._handle.controlWrite(Panda.REQUEST_TYPE, 0xe1, uart, rate, b'')

View File

@@ -4,6 +4,7 @@ import os
import sys
import time
import random
import argparse
from hexdump import hexdump
from itertools import permutations
@@ -14,7 +15,7 @@ from panda import Panda
def get_test_string():
return b"test"+os.urandom(10)
def run_test():
def run_test(sleep_duration):
pandas = Panda.list()
print(pandas)
@@ -25,9 +26,9 @@ def run_test():
if len(pandas) == 1:
# if we only have one on USB, assume the other is on wifi
pandas.append("WIFI")
run_test_w_pandas(pandas)
run_test_w_pandas(pandas, sleep_duration)
def run_test_w_pandas(pandas):
def run_test_w_pandas(pandas, sleep_duration):
h = list(map(lambda x: Panda(x), pandas))
print("H", h)
@@ -38,6 +39,12 @@ def run_test_w_pandas(pandas):
for ho in permutations(range(len(h)), r=2):
print("***************** TESTING", ho)
panda0, panda1 = h[ho[0]], h[ho[1]]
if(panda0._serial == "WIFI"):
print(" *** Can not send can data over wifi panda. Skipping! ***")
continue
# **** test health packet ****
print("health", ho[0], h[ho[0]].health())
@@ -60,29 +67,18 @@ def run_test_w_pandas(pandas):
hexdump(ret)
assert st == ret
print("K/L pass", bus, ho, "\n")
time.sleep(sleep_duration)
# **** test can line loopback ****
for bus in [0,1,4,5,6]:
panda0 = h[ho[0]]
panda1 = h[ho[1]]
for bus, gmlan in [(0, None), (1, False), (2, False), (1, True), (2, True)]:
print("\ntest can", bus)
# flush
cans_echo = panda0.can_recv()
cans_loop = panda1.can_recv()
# set GMLAN mode
if bus == 5:
panda0.set_gmlan(True,2)
panda1.set_gmlan(True,2)
bus = 1 # GMLAN is multiplexed with CAN2
elif bus == 6:
# on REV B panda, this just retests CAN2 GMLAN
panda0.set_gmlan(True,3)
panda1.set_gmlan(True,3)
bus = 4 # GMLAN is also multiplexed with CAN3
else:
panda0.set_gmlan(False)
panda1.set_gmlan(False)
if gmlan is not None:
panda0.set_gmlan(gmlan, bus)
panda1.set_gmlan(gmlan, bus)
# send the characters
# pick addresses high enough to not conflict with honda code
@@ -106,20 +102,23 @@ def run_test_w_pandas(pandas):
assert cans_echo[0][2] == st
assert cans_loop[0][2] == st
assert cans_echo[0][3] == bus+2
assert cans_echo[0][3] == 0x80 | bus
if cans_loop[0][3] != bus:
print("EXPECTED %d GOT %d" % (bus, cans_loop[0][3]))
assert cans_loop[0][3] == bus
print("CAN pass", bus, ho)
time.sleep(sleep_duration)
if __name__ == "__main__":
if len(sys.argv) > 1:
for i in range(int(sys.argv[1])):
run_test()
else :
i = 0
parser = argparse.ArgumentParser()
parser.add_argument("-n", type=int, help="Number of test iterations to run")
parser.add_argument("-sleep", type=int, help="Sleep time between tests", default=0)
args = parser.parse_args()
if args.n is None:
while True:
print("************* testing %d" % i)
run_test()
i += 1
run_test(sleep_duration=args.sleep)
else:
for i in range(args.n):
run_test(sleep_duration=args.sleep)