Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Sending CAN messages on peripherals 1 and 2 #142

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions common/daq/can_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
"msg_id_override":{
"type":"string",
"description":"sets the message to a specific id, ignoring the node's ssa\nTo use hex do \"0x########\""
},
"can_peripheral_override":{
"type":"string",
"enum": ["CAN1", "CAN2"],
"description": "sets the peripheral for a single message, overriding the node's and default"
}
}
},
Expand All @@ -109,7 +114,7 @@
"type":"integer",
"description":"length in bits, only valid if unsigned data type",
"minimum":1,
"maimum":64
"maximum":64
},
"scale":{"type":"number", "description":"scale factor to apply, default of 1\nDecoding results in (x * scale)+offset"},
"offset":{"type":"number", "description": "offset to apply, default of 0\nDecoding results in (x * scale)+offset"},
Expand All @@ -126,7 +131,8 @@
"msg_name":{"type":"string"},
"callback":{"type":"boolean"},
"irq":{"type":"boolean"},
"arg_type":{"type":"string", "enum":["msg_data", "header"]}
"arg_type":{"type":"string", "enum":["msg_data", "header"]
}
}
}
}
Expand Down
173 changes: 112 additions & 61 deletions common/daq/generation/gen_embedded_can.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
gen_can_enums_start = "BEGIN AUTO CAN ENUMERATIONS"
gen_can_enums_stop = "END AUTO CAN ENUMERATIONS"

DEFAULT_PERIPHERAL = "CAN1"
DEFAULT_PERIPHERAL_NODE = "CAN1"

def find_rx_messages(rx_names):
"""
Expand Down Expand Up @@ -79,35 +79,79 @@ def gen_send_macro(lines, msg_config, peripheral):
lines.append(f" }} while(0)\n")

def gen_filter_lines(lines, rx_msg_configs, peripheral):
# peripheral being passed in is node-wise
""" generates hardware filters for a set of message definitions for a specific peripheral """
on_mask = False
filter_bank = 0
filter_bank_max = 27

if peripheral == "CAN1":
filter_bank = 0
filter_bank_max = 14
elif peripheral == "CAN2":
filter_bank = 14
filter_bank_max = 27
else:
print(f"Unknown CAN peripheral {peripheral}")
tlp = peripheral
on_mask_periph = {"CAN1": False, "CAN2": False} # separated for safety (i don't know what this does)
filter_bank_periph = {"CAN1": 0, "CAN2": 14}
filter_bank_max_periph = {"CAN1": 14, "CAN2": 27}

# these lines were default behavior, just moved into tuples above and symbols renamed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small thing, if you are talking about lines 85-87, those are dictionaries and not tuples.

# if peripheral == "CAN1":
# filter_bank = 0
# filter_bank_max = 14
# elif peripheral == "CAN2":
# filter_bank = 14
# filter_bank_max = 27

can1_msgs = []
can2_msgs = []

# look for messages on each bus

for msg in rx_msg_configs:
if(filter_bank > filter_bank_max):

if 'can_peripheral_override' in msg:
print(f"rx can override detected in {msg}")
# use overridden periph
peripheral = msg['can_peripheral_override']
else:
peripheral = tlp

if peripheral == "CAN1":
can1_msgs.append(msg)
if peripheral == "CAN2":
can2_msgs.append(msg)

# split old loop into two to ensure correct filter writing in genned code
for msg in can1_msgs:
peripheral = "CAN1"
if(filter_bank_periph[peripheral] > filter_bank_max_periph[peripheral]):
generator.log_error(f"Max filter bank reached for node containing msg {msg['msg_name']}")
quit(1)

# For extended id vs standard id
shift_phrase = f"(ID_{msg['msg_name'].upper()} << 3) | 4" if ('is_normal' not in msg or msg['is_normal'] == False) else \
f"(ID_{msg['msg_name'].upper()} << 21)"
if not on_mask:
lines.append(f" CAN1->FA1R |= (1 << {filter_bank}); // configure bank {filter_bank}\n")
lines.append(f" CAN1->sFilterRegister[{filter_bank}].FR1 = {shift_phrase};\n")
on_mask = True
f"(ID_{msg['msg_name'].upper()} << 21)"
if not on_mask_periph[peripheral]:
lines.append(f" CAN1->FA1R |= (1 << {filter_bank_periph[peripheral]}); // configure bank {filter_bank_periph[peripheral]}\n")
lines.append(f" CAN1->sFilterRegister[{filter_bank_periph[peripheral]}].FR1 = {shift_phrase};\n")
on_mask_periph[peripheral] = True
else:
lines.append(f" CAN1->sFilterRegister[{filter_bank}].FR2 = {shift_phrase};\n")
on_mask = False
filter_bank += 1
lines.append(f" CAN1->sFilterRegister[{filter_bank_periph[peripheral]}].FR2 = {shift_phrase};\n")
on_mask_periph[peripheral] = False
filter_bank_periph[peripheral] += 1

for msg in can2_msgs:
peripheral = "CAN2"
if(filter_bank_periph[peripheral] > filter_bank_max_periph[peripheral]):
generator.log_error(f"Max filter bank reached for node containing msg {msg['msg_name']}")
quit(1)

# For extended id vs standard id
shift_phrase = f"(ID_{msg['msg_name'].upper()} << 3) | 4" if ('is_normal' not in msg or msg['is_normal'] == False) else \
f"(ID_{msg['msg_name'].upper()} << 21)"
if not on_mask_periph[peripheral]:
lines.append(f" CAN1->FA1R |= (1 << {filter_bank_periph[peripheral]}); // configure bank {filter_bank_periph[peripheral]}\n")
lines.append(f" CAN1->sFilterRegister[{filter_bank_periph[peripheral]}].FR1 = {shift_phrase};\n")
on_mask_periph[peripheral] = True
else:
lines.append(f" CAN1->sFilterRegister[{filter_bank_periph[peripheral]}].FR2 = {shift_phrase};\n")
on_mask_periph[peripheral] = False
filter_bank_periph[peripheral] += 1




def gen_switch_case(lines, rx_msg_configs, rx_callbacks, ind=""):
""" generates switch case for receiving messages """
Expand Down Expand Up @@ -154,30 +198,30 @@ def configure_node(node_config, node_paths):
print("Configuring Node " + node_config['node_name'])

# Junction node?
is_junc = False
junc_config = None
if 'is_junction' in node_config and node_config['is_junction']:
is_junc = True
print(f"Treating {node_config['node_name']} as junction")
global can_config
for bus in can_config['busses']:
for node in bus['nodes']:
if node['node_name'] == node_config['node_name'] and node['can_peripheral'] != node_config['can_peripheral']:
junc_config = node
break
if junc_config: break
# is_junc = False
# junc_config = None
# if 'is_junction' in node_config and node_config['is_junction']:
# is_junc = True
# print(f"Treating {node_config['node_name']} as junction")
# global can_config
# for bus in can_config['busses']:
# for node in bus['nodes']:
# if node['node_name'] == node_config['node_name'] and node['can_peripheral'] != node_config['can_peripheral']:
# junc_config = node
# break
# if junc_config: break

# Combine message definitions
raw_msg_defs = []
raw_msg_defs += node_config['tx']
if is_junc: raw_msg_defs += junc_config['tx']
# if is_junc: raw_msg_defs += junc_config['tx']
receiving_msg_defs = []
node_specific_rx_msg_defs = find_rx_messages([rx_config["msg_name"] for rx_config in node_config['rx']])
receiving_msg_defs += node_specific_rx_msg_defs
junc_rx_msg_defs = []
if is_junc:
junc_rx_msg_defs += find_rx_messages([rx_config['msg_name'] for rx_config in junc_config['rx']])
receiving_msg_defs += junc_rx_msg_defs
# junc_rx_msg_defs = []
# if is_junc:
# junc_rx_msg_defs += find_rx_messages([rx_config['msg_name'] for rx_config in junc_config['rx']])
# receiving_msg_defs += junc_rx_msg_defs
for new_msg in receiving_msg_defs:
if new_msg not in raw_msg_defs:
raw_msg_defs.append(new_msg)
Expand All @@ -201,14 +245,19 @@ def configure_node(node_config, node_paths):

# Send Macros, requires knowledge of CAN peripheral
macro_lines = []
periph = DEFAULT_PERIPHERAL
periph = DEFAULT_PERIPHERAL_NODE
if 'can_peripheral' in node_config: periph = node_config['can_peripheral']
for msg in node_config['tx']:
periph = DEFAULT_PERIPHERAL_NODE

if 'can_peripheral_override' in msg:
periph = msg['can_peripheral_override']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation seems a bit too deep. I have no idea if python will get mad at this or not.

# print(f"found override in {msg}")
gen_send_macro(macro_lines, msg, periph)
if is_junc:
periph = junc_config['can_peripheral']
for msg in junc_config['tx']:
gen_send_macro(macro_lines, msg, periph)
# if is_junc:
# periph = junc_config['can_peripheral']
# for msg in junc_config['tx']:
# gen_send_macro(macro_lines, msg, periph)
h_lines = generator.insert_lines(h_lines, gen_send_macro_start, gen_send_macro_stop, macro_lines)

# Message update periods
Expand Down Expand Up @@ -263,7 +312,7 @@ def configure_node(node_config, node_paths):

# Rx callbacks
rx_callbacks = [rx_config for rx_config in node_config['rx'] if ("callback" in rx_config and rx_config["callback"])]
if is_junc: rx_callbacks += [rx_config for rx_config in junc_config['rx'] if ("callback" in rx_config and rx_config["callback"])]
# if is_junc: rx_callbacks += [rx_config for rx_config in junc_config['rx'] if ("callback" in rx_config and rx_config["callback"])]
extern_callback_lines = [f"extern void {rx_config['msg_name']}_CALLBACK(CanMsgTypeDef_t* msg_header_a);\n" for rx_config in rx_callbacks if ("arg_type" in rx_config and rx_config["arg_type"]=="header")]
extern_callback_lines += [f"extern void {rx_config['msg_name']}_CALLBACK(CanParsedData_t* msg_data_a);\n" for rx_config in rx_callbacks if (("fault" not in rx_config) and (("arg_type" not in rx_config) or rx_config["arg_type"]=="msg_data"))]
extern_callback_lines += "extern void handleCallbacks(uint16_t id, bool latched);\n"
Expand All @@ -274,7 +323,7 @@ def configure_node(node_config, node_paths):


rx_irq_names = [rx_config['msg_name'] for rx_config in node_config['rx'] if ("irq" in rx_config and rx_config["irq"])]
if is_junc: rx_irq_names += [rx_config['msg_name'] for rx_config in junc_config['rx'] if ("irq" in rx_config and rx_config["irq"])]
# if is_junc: rx_irq_names += [rx_config['msg_name'] for rx_config in junc_config['rx'] if ("irq" in rx_config and rx_config["irq"])]
extern_callback_lines = [f"extern void {msg_name}_IRQ(CanParsedData_t* msg_data_a);\n" for msg_name in rx_irq_names]
h_lines = generator.insert_lines(h_lines, gen_irq_extern_start, gen_irq_extern_stop, extern_callback_lines)

Expand All @@ -291,27 +340,29 @@ def configure_node(node_config, node_paths):

# Rx switch case
case_lines = []
periph = DEFAULT_PERIPHERAL
periph = DEFAULT_PERIPHERAL_NODE
if 'can_peripheral' in node_config: periph = node_config['can_peripheral']

ind = ""
if is_junc:
ind = " "
# add if statement for distinguishing between peripherals
case_lines.append(f" if (msg_header.Bus == {periph})\n")
case_lines.append(f" {{\n")
# if is_junc:
# ind = " "
# # add if statement for distinguishing between peripherals
# case_lines.append(f" if (msg_header.Bus == {periph})\n")
# case_lines.append(f" {{\n")
gen_switch_case(case_lines, node_specific_rx_msg_defs, rx_callbacks, ind=ind)
if is_junc:
periph = junc_config['can_peripheral']
case_lines.append(" }\n")
case_lines.append(f" else if (msg_header.Bus == {periph})\n")
case_lines.append(" {\n")
gen_switch_case(case_lines, junc_rx_msg_defs, rx_callbacks, ind=ind)
case_lines.append(" }\n")
# if is_junc:
# periph = junc_config['can_peripheral']
# case_lines.append(" }\n")
# case_lines.append(f" else if (msg_header.Bus == {periph})\n")
# case_lines.append(" {\n")
# gen_switch_case(case_lines, junc_rx_msg_defs, rx_callbacks, ind=ind)
# case_lines.append(" }\n")
c_lines = generator.insert_lines(c_lines, gen_switch_case_start, gen_switch_case_stop, case_lines)

# Stale checking
stale_lines = []
for msg in receiving_msg_defs:
if 'can_peripheral_override' in msg: periph = msg['can_peripheral_override']
if msg['msg_period'] > 0:
stale_lines.append(f" CHECK_STALE(can_data.{msg['msg_name']}.stale,\n")
stale_lines.append(f" sched.os_ticks, can_data.{msg['msg_name']}.last_rx,\n")
Expand All @@ -321,10 +372,10 @@ def configure_node(node_config, node_paths):
# Hardware filtering
filter_lines = []
if not ("accept_all_messages" in node_config and node_config["accept_all_messages"]):
periph = DEFAULT_PERIPHERAL
periph = DEFAULT_PERIPHERAL_NODE
if "can_peripheral" in node_config: periph = node_config['can_peripheral']
gen_filter_lines(filter_lines, node_specific_rx_msg_defs, periph)
if is_junc: gen_filter_lines(filter_lines, junc_rx_msg_defs, junc_config['can_peripheral'])
# if is_junc: gen_filter_lines(filter_lines, junc_rx_msg_defs, junc_config['can_peripheral'])

c_lines = generator.insert_lines(c_lines, gen_filter_start, gen_filter_stop, filter_lines)

Expand Down
2 changes: 1 addition & 1 deletion common/daq/generation/gen_embedded_daq.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def generate_daq_can_msgs(daq_config, can_config):
can_node['tx'].append(rsp_msg)

# add to daq config
periph = gen_embedded_can.DEFAULT_PERIPHERAL
periph = gen_embedded_can.DEFAULT_PERIPHERAL_NODE
if 'can_periperal' in can_node: periph = can_node['can_peripheral']
daq_node_config['daq_rsp_msg_periph'] = periph

Expand Down
50 changes: 25 additions & 25 deletions common/daq/generation/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,30 +173,30 @@ def check_repeat_daq_variables(daq_config):
else:
eeprom_lbls.append(var['eeprom']['label'])

def label_junction_nodes(can_config):
""" Finds junction nodes, ensures can peripherals defined, and adds is_junction """
node_names = []
for bus in can_config['busses']:
for node in bus['nodes']:
if node['node_name'] in node_names:
if ('DAQ' == node['node_name']): continue
# junction found (assumes check repeat defs already ran and passed)
print(f"Junction node found: {node['node_name']}")
node['is_junction'] = True
# check peripheral
if 'can_peripheral' not in node:
log_error(f"ERROR: can peripheral not defined for junction node {node['node_name']}")
quit(1)
# label the matching nodes on the other busses as a junction
for bus2 in can_config['busses']:
for node2 in bus2['nodes']:
if node2['node_name'] == node['node_name']:
node2['is_junction'] = True
# check peripheral
if 'can_peripheral' not in node2:
log_error(f"ERROR: can peripheral not defined for junction node {node2['node_name']}")
quit(1)
node_names.append(node['node_name'])
# def label_junction_nodes(can_config):
# """ Finds junction nodes, ensures can peripherals defined, and adds is_junction """
# node_names = []
# for bus in can_config['busses']:
# for node in bus['nodes']:
# if node['node_name'] in node_names:
# if ('DAQ' == node['node_name']): continue
# # junction found (assumes check repeat defs already ran and passed)
# print(f"Junction node found: {node['node_name']}")
# node['is_junction'] = True
# # check peripheral
# if 'can_peripheral' not in node:
# log_error(f"ERROR: can peripheral not defined for junction node {node['node_name']}")
# quit(1)
# # label the matching nodes on the other busses as a junction
# for bus2 in can_config['busses']:
# for node2 in bus2['nodes']:
# if node2['node_name'] == node['node_name']:
# node2['is_junction'] = True
# # check peripheral
# if 'can_peripheral' not in node2:
# log_error(f"ERROR: can peripheral not defined for junction node {node2['node_name']}")
# quit(1)
# node_names.append(node['node_name'])

def insert_lines(source: list, start, stop, new_lines):
"""
Expand Down Expand Up @@ -333,7 +333,7 @@ def generate_all():
generate_ids(can_config)
generate_dlcs(can_config)
check_repeat_defs(can_config)
label_junction_nodes(can_config)
# label_junction_nodes(can_config)

gen_embedded_can.gen_embedded_can(can_config, firmware_source_dir, gen_config['node_parse_c_dir'], gen_config['node_parse_h_dir'])
gen_embedded_daq.gen_embedded_daq(daq_config, firmware_source_dir, gen_config['node_daq_c_dir'], gen_config['node_daq_h_dir'])
Expand Down