drivers: can: stm32: rework filter handling

The previous driver implementation aimed to maximize the amount of
filters, which resulted in a fairly complex implementation.

Background: The bxCAN assigns a number to the filters in the order they
appear in the filter banks. This number is used to match messages in
the FIFO with their filter. If the scale or mode of a filter bank is
changed, all following filter numbers get an offset and the assigned
callbacks have to be shifted accordingly.

The required additional space for the shifting operations resulted in
non-deterministic behaviour and the maximum number of filters could not
be determined at compile-time, which made several tests like
tests/drivers/can/api fail.

This implementation uses a more simple but reliable approach for
filtering and and reserves fixed space for extended and standard ID
filters in the available banks (configurable via Kconfig).
The list mode is not used, which may reduce the total number of usable
filters depending on the application.

The maximum amount of filters is 14 if all filters use ext. IDs,
28 if all use std IDs and something in between if mixed IDs are used.

Also see issue #47986 for more detailed background information.

Signed-off-by: Martin Jäger <martin@libre.solar>
This commit is contained in:
Martin Jäger
2022-07-23 08:01:10 +02:00
committed by Fabio Baltieri
parent 3524958083
commit c56b1dbca1
3 changed files with 177 additions and 331 deletions

View File

@@ -12,11 +12,34 @@ config CAN_STM32
Enable STM32 CAN Driver.
Tested on STM32F0, STM32F4, STM32L4 and STM32F7 series.
config CAN_MAX_FILTER
int "Maximum number of concurrent active filters"
depends on CAN_STM32
default 5
range 1 56
config CAN_MAX_STD_ID_FILTER
int "Maximum number of std ID filters"
default 14
range 0 28
help
Defines the array size of the callback pointers.
Must be at least the size of concurrent reads.
Defines the maximum number of filters with standard ID (11-bit)
that can be added by the application.
One standard ID filter with mask occupies 1/2 of the 14 available
filter banks.
The following equation determines the maximum total number of
filters:
CAN_MAX_STD_ID_FILTER + CAN_MAX_EXT_ID_FILTER * 2 <= 28
config CAN_MAX_EXT_ID_FILTER
int "Maximum number of ext ID filters"
default 7
range 0 14
help
Defines the maximum number of filters with extended ID (29-bit)
that can be added by the application.
One extended ID filter with mask occupies 1 of the 14 available
filter banks.
The following equation determines the maximum total number of
filters:
CAN_MAX_STD_ID_FILTER + CAN_MAX_EXT_ID_FILTER * 2 <= 28

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,8 @@
#include <zephyr/drivers/can.h>
#define CAN_STM32_NUM_FILTER_BANKS (14)
#define CAN_STM32_MAX_NUM_FILTERS (CAN_STM32_NUM_FILTER_BANKS * 4)
#define CAN_STM32_MAX_FILTER_ID \
(CONFIG_CAN_MAX_EXT_ID_FILTER + CONFIG_CAN_MAX_STD_ID_FILTER * 2)
#define CAN_STM32_FIRX_STD_IDE_POS (3U)
#define CAN_STM32_FIRX_STD_RTR_POS (4U)
@@ -21,9 +22,6 @@
#define CAN_STM32_FIRX_EXT_STD_ID_POS (21U)
#define CAN_STM32_FIRX_EXT_EXT_ID_POS (3U)
#define CAN_STM32_BANK_IS_EMPTY(usage, bank_nr, bank_offset) \
(((usage >> ((bank_nr - bank_offset) * 4)) & 0x0F) == 0x0F)
struct can_stm32_mailbox {
can_tx_callback_t tx_callback;
void *callback_arg;
@@ -31,23 +29,16 @@ struct can_stm32_mailbox {
int error;
};
/* number = FSCx | FMBx */
enum can_stm32_filter_type {
CAN_STM32_FILTER_STANDARD_MASKED = 0,
CAN_STM32_FILTER_STANDARD = 1,
CAN_STM32_FILTER_EXTENDED_MASKED = 2,
CAN_STM32_FILTER_EXTENDED = 3
};
struct can_stm32_data {
struct k_mutex inst_mutex;
struct k_sem tx_int_sem;
struct can_stm32_mailbox mb0;
struct can_stm32_mailbox mb1;
struct can_stm32_mailbox mb2;
uint64_t filter_usage;
can_rx_callback_t rx_cb[CONFIG_CAN_MAX_FILTER];
void *cb_arg[CONFIG_CAN_MAX_FILTER];
can_rx_callback_t rx_cb_std[CONFIG_CAN_MAX_STD_ID_FILTER];
can_rx_callback_t rx_cb_ext[CONFIG_CAN_MAX_EXT_ID_FILTER];
void *cb_arg_std[CONFIG_CAN_MAX_STD_ID_FILTER];
void *cb_arg_ext[CONFIG_CAN_MAX_EXT_ID_FILTER];
can_state_change_callback_t state_change_cb;
void *state_change_cb_data;
enum can_state state;