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

Timestamped Frames #10

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4629e6f
Timestamped_Frame struct
equationcrunchor Apr 27, 2019
20f88aa
Generate timestamped structs
equationcrunchor Apr 27, 2019
abdaaa7
Handle timestamped frames
equationcrunchor Apr 27, 2019
235d4c3
Fix bugs
equationcrunchor Apr 27, 2019
cda72b5
Merge branch 'interrupts' into timestamped-frames
equationcrunchor Apr 27, 2019
e40b75c
CANlib_ReadFrame now checks if frame is valid
equationcrunchor Apr 27, 2019
cf24235
CANlib_HandleFrame now uses CANlib_ReadFrame
equationcrunchor Apr 27, 2019
0069c3e
Fix typos
equationcrunchor Apr 27, 2019
a11eb1c
Check both FIFOs
equationcrunchor May 1, 2019
fb6cf2e
Prevent unused warning
equationcrunchor May 1, 2019
c60f943
Merge remote-tracking branch 'origin/master' into timestamped-frames
equationcrunchor May 2, 2019
71c463e
Rename TimestampedFrame
equationcrunchor May 2, 2019
bff9a8b
Rename timestamp field to stamp
equationcrunchor May 2, 2019
3989e45
Change name
equationcrunchor May 4, 2019
d9404a3
Change ReadFrame function
equationcrunchor May 4, 2019
1377b3e
Change CANlib_update functions
equationcrunchor May 4, 2019
acc0883
Change CANlib_HandleFrame
equationcrunchor May 4, 2019
616a1f5
HandleFrame returns bool
equationcrunchor May 4, 2019
dd9d9db
New readframe functions
equationcrunchor May 4, 2019
cbd2495
Change HandleFrame
equationcrunchor May 4, 2019
0863f19
Fix mistakes
equationcrunchor May 4, 2019
ac7ab57
Change update can functions
equationcrunchor May 4, 2019
0cfa2d9
Fix typos in update_can and switch on instance
equationcrunchor May 4, 2019
827eeef
Extern C stuff
equationcrunchor May 4, 2019
04a93f5
Fix typo
equationcrunchor May 11, 2019
55267dc
Fix unused
equationcrunchor May 15, 2019
18be57b
Add comment
equationcrunchor Jul 25, 2019
f7dc936
Merge branch 'master' into timestamped-frames
equationcrunchor Jul 25, 2019
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
2 changes: 1 addition & 1 deletion generator/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def write(can, computers, output_path=bus_path):
raw_buses = set()
for computer in computers:
if not ('can' in computer.participation['name'].keys()):
# This computer neither sends nor recieves can messages
# This computer neither sends nor receives can messages
continue

raw_buses |= set(computer.participation['name']['can'].mapping.values())
Expand Down
60 changes: 50 additions & 10 deletions generator/computers_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def single_handler(frame, name_prepends, num_tabs, fw):
tot_name = coord(name_prepends, frame.name, prefix=False)
fw(
'\t' * num_tabs + 'case CANlib_{}_key:'.format(tot_name) + '\n' +
'\t' * (num_tabs + 1) + 'CANlib_Handle_{}(&frame);\n'.format(tot_name) +
'\t' * (num_tabs + 1) + 'CANlib_Handle_{}(ts_frame);\n'.format(tot_name) +
'\t' * (num_tabs + 1) + 'break;\n'
)

Expand All @@ -20,7 +20,7 @@ def multplxd_handler(frame, name_prepends, num_tabs, fw):
fw('\t' * num_tabs + 'case {}_key:\n'.format(coord(name_prepends, frame.name)))
key_size = ceil(frame.slice.length / 8) * 8
key_name = '_'.join([name_prepends,frame.name, 'key'])
fw('\t' * (num_tabs + 1) + 'to_bitstring(frame.data, &bitstring);' '\n')
fw('\t' * (num_tabs + 1) + 'to_bitstring(frame->data, &bitstring);' '\n')
fw(
'\t' * (num_tabs + 1) + 'uint{}_t {} = EXTRACT(bitstring, {}, {});\n'.format(key_size, key_name, frame.slice.start, frame.slice.length) + '\t' * (num_tabs + 1) + 'switch(' + key_name + ') {' '\n'
)
Expand Down Expand Up @@ -78,28 +78,68 @@ def write(can, computers, output_path=computer_c_dir_path):

fw('\t}\n}\n\n')

fw(
'CAN_Raw_Bus_T CANlib_GetConceptualBus(CAN_Raw_Bus_T bus) {\n'
Copy link
Member

Choose a reason for hiding this comment

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

What is this used for?

'\tswitch (bus) {\n'
)

for busnm, rawnm in computer.participation['name']['can'].mapping.items():
fw('\t\tcase {}:\n'.format(rawnm) + '\t\t\treturn {};\n'.format(busnm))

fw('\t\tdefault:\n\t\t\treturn INVALID_BUS;\n')

fw('\t}\n}\n\n')

for busnm, bus in computer.participation['name']['can'].subscribe.items():
fw(
'static void CANlib_update_can_{}(void)'.format(busnm) + '{\n' +
'\tFrame frame;\n'
)
if any(is_multplxd(msg) for msg in bus):
fw('\tuint64_t bitstring;\n')
fw(
'\tCANlib_ReadFrame(&frame, {});\n'.format(busnm) +
'\tswitch(frame.id) {\n'
'static void CANlib_HandleFrame_{}(Timestamped_Frame* ts_frame)'.format(busnm) + '{\n' +
'\tswitch(ts_frame->frame.id) {\n'
)

for msg in bus:
msg_handler(msg, busnm, fw)

fw('\t\tdefault:\n\t\t\treturn;\n')
fw('\t}\n')

fw(
'}\n\n'
)

for busnm, bus in computer.participation['name']['can'].subscribe.items():
fw(
'static void CANlib_update_can_{}(void)'.format(busnm) + '{\n' +
Copy link
Member

Choose a reason for hiding this comment

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

should be _Update and also missing space before {.

'\tTimestamped_Frame ts_frame;\n'
)
if any(is_multplxd(msg) for msg in bus):
Copy link
Member

Choose a reason for hiding this comment

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

Why is this here? Unused

fw('\tuint64_t bitstring;\n')

fw(
'\tif (CANlib_ReadFrame(&(ts_frame.frame), {})) {{\n'.format(busnm) +
Copy link
Member

Choose a reason for hiding this comment

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

You don't set the timestamp so it's initialized with junk. Here you can set it with get tick

'\t\tCANlib_HandleFrame_{}(&ts_frame);\n'.format(busnm) +
'\t}\n' +
'}\n\n'
)

fw('void CANlib_update_can() {\n')
for busnm in computer.participation['name']['can'].subscribe.keys():
fw('\tCANlib_update_can_{}();\n'.format(busnm))
fw('}\n\n')

fw('void CANlib_HandleFrame(CAN_Raw_Bus_T raw_bus) {\n')
Copy link
Member

Choose a reason for hiding this comment

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

How is this different than the update? Where can a user of interrupts provide a timestamped frame and have it accounted for?

if len(computer.participation['name']['can'].subscribe.keys()) > 0: # check if computer receives messages
Copy link
Member

Choose a reason for hiding this comment

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

It's not this part's job to make a function unusable if nobody subscribes to it. It should be generated and just not be exposed to the user.

fw('\tTimestamped_Frame ts_frame;\n')
fw('\tswitch(raw_bus) {\n')
for bus in computer.participation['name']['can'].subscribe.keys():
fw(
'\t\tcase {}:\n'.format(computer.participation['name']['can'].mapping[bus]) +
'\t\t\tif (CANlib_ReadFrame(&(ts_frame.frame), {})) {{\n'.format(bus) +
'\t\t\t\tCANlib_HandleFrame_{}(&ts_frame);\n'.format(bus) +
'\t\t\t}\n' +
'\t\t\tbreak;\n'
)
fw('\t\tdefault:\n\t\t\tbreak;\n')
fw('\t}\n')
else: # prevent unused warning
fw('\tUNUSED(raw_bus);\n')
fw('}\n')
14 changes: 8 additions & 6 deletions generator/computers_h.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def declare_pub_frame(frame, name_prepends, fw):
def declare_sub_frame(frame, name_prepends, fw):
tot_name = coord(name_prepends, frame.name, prefix=False)
fw(
'extern CANlib_{}_T CANlib_{}_Input;\n'.format(tot_name, tot_name) +
'void CANlib_Handle_{}(Frame *frame);\n'.format(tot_name, tot_name)
'extern CANlib_{}_Timestamped_T CANlib_{}_Input;\n'.format(tot_name, tot_name) +
'void CANlib_Handle_{}(Timestamped_Frame *frame);\n'.format(tot_name, tot_name)
)


Expand All @@ -26,7 +26,7 @@ def write(can, computers, output_path=computer_h_dir_path):
f_path = os.path.join(output_path, 'canlib_{}.h'.format(computer.name))

if not ('can' in computer.participation['name'].keys()):
# This computer neither sends nor recieves can messagess
# This computer neither sends nor receives can messages
continue

with open(f_path, 'w') as f:
Expand All @@ -41,7 +41,8 @@ def write(can, computers, output_path=computer_h_dir_path):
fw('#include "structs.h"\n')
fw('#include "static.h"\n')
fw('#include "evil_macros.h"\n')
fw('#include "pack_unpack.h"\n\n')
fw('#include "pack_unpack.h"\n')
fw('#include "bus.h"\n\n')

fw('\n')

Expand All @@ -53,7 +54,7 @@ def write(can, computers, output_path=computer_h_dir_path):
for frame in bus:
frame_handler(frame, bus_name, declare_pub_frame, fw)
except KeyError:
pass # No CAN messages sent by this board
pass # No CAN messages sent by this board

fw('\n')

Expand All @@ -64,8 +65,9 @@ def write(can, computers, output_path=computer_h_dir_path):
frame_handler(frame, bus_name, declare_sub_frame, fw)
fw('\n')
fw('void CANlib_update_can(void);\n')
fw('void CANlib_HandleFrame(CAN_Raw_Bus_T raw_bus);\n')
except KeyError:
pass # No CAN messages received by this board
pass # No CAN messages received by this board

fw('\n#ifdef __cplusplus\n} // extern "C"\n#endif // __cplusplus\n\n')

Expand Down
9 changes: 6 additions & 3 deletions generator/send_receive.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,22 @@ def define_pub_frame(frame, name_prepends, busnm, fw):
def define_sub_frame(frame, name_prepends, fw):
tot_name = coord(name_prepends, frame.name,
prefix=False)
fw('void CANlib_Handle_{}(Frame *frame)'.format(
tot_name, tot_name) + ' {\n' + '\tCANlib_Unpack_{}(frame, &CANlib_{}_Input);\n'.format(tot_name, tot_name) + '}\n\n')
fw('void CANlib_Handle_{}(Timestamped_Frame *ts_frame) {{\n'.format(tot_name, tot_name))
fw('\tCANlib_{}_Input.timestamp = HAL_GetTick();\n'.format(tot_name))
Copy link
Member

Choose a reason for hiding this comment

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

This should be coming in as a function parameter. Devices could be buffering frames on their own and have the timestamp be in the past.

fw('\tCANlib_Unpack_{}(&(ts_frame->frame), &(CANlib_{}_Input.msg));\n'.format(tot_name,tot_name))
fw('}\n\n')


def define_struct(frame, name_prepends, fw):
tot_name = coord(name_prepends, frame.name)
fw('{}_T {}_Input;\n'.format(
fw('{}_Timestamped_T {}_Input;\n'.format(
tot_name, tot_name))


def write(can, output_path=send_recieve_path):
with open(output_path, 'w') as f:
fw = f.write
fw('#include <stm32f4xx_hal.h>\n')
fw('#include "pack_unpack.h"\n\n')

for bus in can.bus:
Expand Down
11 changes: 10 additions & 1 deletion generator/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ def msg_handler(frame, name_prepends, fw):
fw('} ' + '{}_T;\n\n'.format(coord(name_prepends, frame.name)))


def timestamped_msg_handler(frame, name_prepends, fw):
fw('typedef struct {\n')
fw('\t{}_T msg;\n'.format(coord(name_prepends, frame.name)))
fw('\ttime_t timestamp;\n')
fw('} ' + '{}_Timestamped_T;\n\n'.format(coord(name_prepends, frame.name)))


def write(can, output_path=structs_path):
header_name = '_CAN_LIBRARY_STRUCTS'

Expand All @@ -25,10 +32,12 @@ def write(can, output_path=structs_path):

fw(ifndef(header_name))
fw('#include <stdint.h>\n')
fw('#include <stdbool.h>\n\n')
fw('#include <stdbool.h>\n')
fw('#include <time.h>\n')
fw('#include "enum_atom.h"\n\n')

for bus in can.bus:
for msg in bus.frame:
frame_handler(msg, bus.name, msg_handler, fw)
frame_handler(msg, bus.name, timestamped_msg_handler, fw)
fw(endif(header_name))
3 changes: 2 additions & 1 deletion src/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

#include "drivers/inc/stm32f4xx.h"
Copy link
Member

Choose a reason for hiding this comment

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

Oh this really shouldn't be here.

Copy link
Member

Choose a reason for hiding this comment

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

The intent is that each driver header includes driver.h at the bottom, after defining the native types. Then concepts like CANlib_TransmitFrame have a common name and behavior across drivers while still using the native error type.

#include "bus.h"
#include <stdbool.h>
Copy link
Member

Choose a reason for hiding this comment

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

There is a driver specific error type, we shouldn't need bool.


CANlib_Transmit_Error_T CANlib_TransmitFrame(Frame *frame, CANlib_Bus_T bus);
void CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus);
bool CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe introduce CANlib_Receive_Error_T, idk if we need to mess with this now tho

CAN_Raw_Bus_T CANlib_GetRawBus(CANlib_Bus_T bus);

#endif // __DRIVER_H
3 changes: 2 additions & 1 deletion src/drivers/inc/stm32f4xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
#include "bus.h"

#include <stdint.h>
#include <stdbool.h>

typedef uint32_t Time_T; // in ms
typedef HAL_StatusTypeDef CANlib_Transmit_Error_T;
typedef HAL_StatusTypeDef CANlib_Init_Error_T;

CANlib_Transmit_Error_T CANlib_TransmitFrame(Frame *frame, CANlib_Bus_T bus);
Copy link
Member

Choose a reason for hiding this comment

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

This should not be here and driver.h should be included at the bottom.

void CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus);
bool CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus);

#endif // __STM32F4XX_CAN_H
14 changes: 8 additions & 6 deletions src/drivers/src/stm32f4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "driver.h"
Copy link
Member

Choose a reason for hiding this comment

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

This should include the stm specific driver/inc/xxx.h

#include <stdint.h>
#include <string.h>
#include <stdbool.h>

extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
Expand Down Expand Up @@ -38,7 +39,7 @@ HAL_StatusTypeDef CANlib_TransmitFrame(Frame *frame, CANlib_Bus_T bus) {
return HAL_CAN_AddTxMessage(hcan, &pHeader, frame->data, &pTxMailbox);
}

void CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus) {
bool CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus) {
Copy link
Member

Choose a reason for hiding this comment

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

If it returns anything it should probably be HAL_StatusTypeDef.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The thing is HAL_CAN_GetRxMessage only returns HAL_OK or HAL_ERROR anyway; and also it could possibly not even be called if both FIFO's are empty

CAN_Raw_Bus_T raw_bus = CANlib_GetRawBus(bus);
CAN_HandleTypeDef *hcan;
switch(raw_bus) {
Expand All @@ -52,22 +53,23 @@ void CANlib_ReadFrame(Frame *frame, CANlib_Bus_T bus) {
hcan = &hcan3;
break;
default:
return;
return false;
}

uint8_t data[8] = {};
CAN_RxHeaderTypeDef pHeader;
for (int fifo = 0; fifo < 2; fifo++) { // There are 2 receive FIFOs
if (HAL_CAN_GetRxFifoFillLevel(hcan, fifo) > 0) {
HAL_CAN_GetRxMessage(hcan, fifo, &pHeader, data);
if (HAL_CAN_GetRxMessage(hcan, fifo, &pHeader, data) != HAL_OK) {
continue;
}
frame->id = pHeader.IDE == CAN_ID_STD ? pHeader.StdId : pHeader.ExtId;
frame->dlc = pHeader.DLC;

memcpy(frame->data, data, sizeof(data));
frame->extended = pHeader.IDE == CAN_ID_EXT;
return;
return true;
}
}
return false;
}


6 changes: 6 additions & 0 deletions src/static.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <stdint.h>
#include <stdbool.h>
#include <time.h>

typedef struct {
uint32_t id;
Expand All @@ -11,6 +12,11 @@ typedef struct {
bool extended;
} Frame;

typedef struct {
nistath marked this conversation as resolved.
Show resolved Hide resolved
Frame frame;
time_t timestamp;
} Timestamped_Frame;

#define LIMIT(name) \
static Time_T last_sent = 0; \
if (HAL_GetTick() - last_sent < name ## _period) return; \
Expand Down