-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: automatic CAN filter configuration #20
base: main
Are you sure you want to change the base?
Changes from 2 commits
6a99af9
f46f187
b555b35
9e4126c
3008cd3
ae80c5e
aaf21fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -179,26 +179,6 @@ rtcan_status_t rtcan_init(rtcan_handle_t* rtcan_h, | |
ADD_ERROR_IF(tx_status != TX_SUCCESS, RTCAN_ERROR_INTERNAL, rtcan_h); | ||
} | ||
|
||
// TODO: configure CAN filters | ||
if (no_errors(rtcan_h)) | ||
{ | ||
CAN_FilterTypeDef filter; | ||
filter.FilterActivation = ENABLE; | ||
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; | ||
filter.FilterIdHigh = 0x0000 << 5U; | ||
filter.FilterIdLow = 0x0000 << 5U; | ||
filter.FilterMaskIdHigh = 0x0000 << 5U; | ||
filter.FilterMaskIdLow = 0x0000 << 5U; | ||
filter.FilterMode = CAN_FILTERMODE_IDMASK; | ||
filter.FilterScale = CAN_FILTERSCALE_16BIT; | ||
filter.FilterBank = 0; | ||
|
||
HAL_StatusTypeDef hal_status = HAL_CAN_ConfigFilter(rtcan_h->hcan, | ||
&filter); | ||
|
||
ADD_ERROR_IF(hal_status != HAL_OK, RTCAN_ERROR_INIT, rtcan_h); | ||
} | ||
|
||
return create_status(rtcan_h); | ||
} | ||
|
||
|
@@ -209,6 +189,54 @@ rtcan_status_t rtcan_init(rtcan_handle_t* rtcan_h, | |
*/ | ||
rtcan_status_t rtcan_start(rtcan_handle_t* rtcan_h) | ||
{ | ||
/* Since the subscriber ID list is known, we can configure the CAN ID Filter now */ | ||
|
||
uint32_t can_id_list[RTCAN_HASHMAP_SIZE] = {0}; | ||
int number_ids = 0; | ||
|
||
/* Save and count all CAN IDs stored in hashmap */ | ||
for (uint32_t i = 0; i < RTCAN_HASHMAP_SIZE; i++) | ||
t-bre marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loop iteration limit should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My mistake, you're absolutely right. Honestly no idea what I was thinking sorry! |
||
{ | ||
if(rtcan_h->subscriber_map[i] != NULL) | ||
{ | ||
/* Subscriber found! */ | ||
can_id_list[number_ids] = rtcan_h->subscriber_map[i]->can_id; | ||
number_ids++; | ||
|
||
} | ||
} | ||
|
||
int number_banks = (number_ids-1)/4 + 1; | ||
|
||
/* Error if there's too many ids to apply filter */ | ||
ADD_ERROR_IF(number_banks > 28, RTCAN_ERROR_INIT, rtcan_h); | ||
t-bre marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (no_errors(rtcan_h)) | ||
{ | ||
CAN_FilterTypeDef filter; | ||
filter.FilterActivation = ENABLE; | ||
filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we know what this FIFO assignment does? I don't know if we ever want to use anything other than FIFO0, but maybe its important? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to datasheet: "If there is a match, the message is stored in the associated FIFO". Basically, when there's filter match, the data can be saved either in FIFO0 or FIFO1. Actually, this one may be useful for prioritizing certain IDs over another IDs which are in the same CAN bus. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From slides on the F7 bxCAN peripheral:
So I don't think there's any inherent prioritisation of one FIFO over another, unless we did this as a feature of RTCAN where it will read and distribute the messages from one FIFO first, but I don't think we need that level of prioritisation. I think we might want to consider using both FIFOs to share the load (so we use all 6 available message slots rather than just the 3 in FIFO0). Maybe having it alternate between FIFOs each loop? |
||
filter.FilterMode = CAN_FILTERMODE_IDLIST; | ||
filter.FilterScale = CAN_FILTERSCALE_16BIT; | ||
|
||
/* Configure Filter IDs for each filter bank */ | ||
for(int i = 0; i < number_banks; i++) | ||
{ | ||
filter.FilterIdHigh = can_id_list[4 * i] << 5U; | ||
filter.FilterIdLow = can_id_list[4 * i + 1] << 5U; | ||
filter.FilterMaskIdHigh = can_id_list[4 * i + 2] << 5U; | ||
filter.FilterMaskIdLow = can_id_list[4 * i + 3] << 5U; | ||
filter.FilterBank = i; | ||
|
||
|
||
HAL_StatusTypeDef hal_status = HAL_CAN_ConfigFilter(rtcan_h->hcan, | ||
&filter); | ||
|
||
ADD_ERROR_IF(hal_status != HAL_OK, RTCAN_ERROR_INIT, rtcan_h); | ||
} | ||
} | ||
|
||
|
||
TX_THREAD* threads[2] = {&rtcan_h->tx_thread, &rtcan_h->rx_thread}; | ||
|
||
for (uint32_t i = 0; i < 2; i++) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps counterintuitively there can be more subscribers than hashmap entries, so I think the size of this array should be replaced with something like
NUM_IDS_PER_FILTER * NUM_FILTERS
.The reason there can be more subscribers than hashmap entries is that when two IDs result in a hash collision (same hash for different CAN ID), they are combined in that hashmap entry as a singly linked list using "separate chaining" (there are some notes in the docs folder about this implementation). The actual subscribers are allocated from a memory pool, which is ultimately what determines the maximum number of subscriptions.