23class Can<Handle, FDCAN_HandleTypeDef *> :
public CanBase {
26 : std_rx_queues_(Handle->Init.StdFiltersNbr, nullptr),
27 ext_rx_queues_(Handle->Init.ExtFiltersNbr, nullptr) {
28 stm32cubemx_helper::set_context<Handle, Can>(
this);
29 HAL_FDCAN_RegisterRxFifo0Callback(
30 Handle, [](FDCAN_HandleTypeDef *hfdcan, uint32_t) {
31 static FDCAN_RxHeaderTypeDef rx_header;
34 auto fdcan = stm32cubemx_helper::get_context<Handle, Can>();
36 while (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header,
37 msg.
data.data()) == HAL_OK) {
38 if (rx_header.IsFilterMatchingFrame == 1) {
41 if (rx_header.IdType == FDCAN_STANDARD_ID) {
42 if (rx_header.FilterIndex >= fdcan->std_rx_queues_.size()) {
46 fdcan->std_rx_queues_[rx_header.FilterIndex];
48 update_rx_message(msg, rx_header);
49 rx_queue->
push(msg, 0);
51 }
else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
52 if (rx_header.FilterIndex >= fdcan->ext_rx_queues_.size()) {
56 fdcan->ext_rx_queues_[rx_header.FilterIndex];
58 update_rx_message(msg, rx_header);
59 rx_queue->
push(msg, 0);
67 HAL_FDCAN_UnRegisterRxFifo0Callback(Handle);
68 stm32cubemx_helper::set_context<Handle, Can>(
nullptr);
72 if (HAL_FDCAN_ConfigGlobalFilter(Handle, FDCAN_REJECT, FDCAN_REJECT,
74 FDCAN_REJECT_REMOTE) != HAL_OK) {
77 if (HAL_FDCAN_ActivateNotification(Handle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
81 return HAL_FDCAN_Start(Handle) == HAL_OK;
85 if (HAL_FDCAN_Stop(Handle) != HAL_OK) {
88 return HAL_FDCAN_DeactivateNotification(
89 Handle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == HAL_OK;
93 FDCAN_TxHeaderTypeDef tx_header = create_tx_header(msg);
95 while (HAL_FDCAN_AddMessageToTxFifoQ(Handle, &tx_header, msg.
data.data()) !=
108 size_t rx_queue_index = find_ext_rx_queue_index(
nullptr);
109 if (rx_queue_index >= ext_rx_queues_.size()) {
112 FDCAN_FilterTypeDef filter_config =
113 create_filter_config(filter, rx_queue_index);
114 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
117 ext_rx_queues_[rx_queue_index] = &queue;
119 size_t rx_queue_index = find_std_rx_queue_index(
nullptr);
120 if (rx_queue_index >= std_rx_queues_.size()) {
123 FDCAN_FilterTypeDef filter_config =
124 create_filter_config(filter, rx_queue_index);
125 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
128 std_rx_queues_[rx_queue_index] = &queue;
134 size_t rx_queue_index = find_std_rx_queue_index(&queue);
135 if (rx_queue_index < std_rx_queues_.size()) {
136 FDCAN_FilterTypeDef filter_config{};
137 filter_config.FilterIndex = rx_queue_index;
138 filter_config.FilterConfig = FDCAN_FILTER_DISABLE;
139 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
142 std_rx_queues_[rx_queue_index] =
nullptr;
144 rx_queue_index = find_ext_rx_queue_index(&queue);
145 if (rx_queue_index >= ext_rx_queues_.size()) {
148 FDCAN_FilterTypeDef filter_config{};
149 filter_config.FilterIndex = rx_queue_index;
150 filter_config.FilterConfig = FDCAN_FILTER_DISABLE;
151 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
154 ext_rx_queues_[rx_queue_index] =
nullptr;
160 std::vector<core::Queue<CanMessage> *> std_rx_queues_{};
161 std::vector<core::Queue<CanMessage> *> ext_rx_queues_{};
163 Can(
const Can &) =
delete;
164 Can &operator=(
const Can &) =
delete;
166 size_t find_std_rx_queue_index(
const core::Queue<CanMessage> *queue) {
167 return std::distance(
168 std_rx_queues_.begin(),
169 std::find(std_rx_queues_.begin(), std_rx_queues_.end(), queue));
172 size_t find_ext_rx_queue_index(
const core::Queue<CanMessage> *queue) {
173 return std::distance(
174 ext_rx_queues_.begin(),
175 std::find(ext_rx_queues_.begin(), ext_rx_queues_.end(), queue));
178 static inline FDCAN_FilterTypeDef
179 create_filter_config(
const CanFilter &filter, uint32_t filter_index) {
180 FDCAN_FilterTypeDef filter_config{};
182 filter_config.IdType = FDCAN_EXTENDED_ID;
184 filter_config.IdType = FDCAN_STANDARD_ID;
186 filter_config.FilterIndex = filter_index;
187 filter_config.FilterType = FDCAN_FILTER_MASK;
188 filter_config.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
189 filter_config.FilterID1 = filter.id;
190 filter_config.FilterID2 = filter.mask;
191 return filter_config;
194 static inline FDCAN_TxHeaderTypeDef create_tx_header(
const CanMessage &msg) {
195 FDCAN_TxHeaderTypeDef tx_header{};
196 tx_header.Identifier = msg.id;
198 tx_header.IdType = FDCAN_EXTENDED_ID;
200 tx_header.IdType = FDCAN_STANDARD_ID;
202 tx_header.TxFrameType = FDCAN_DATA_FRAME;
205 tx_header.DataLength = FDCAN_DLC_BYTES_0;
208 tx_header.DataLength = FDCAN_DLC_BYTES_1;
211 tx_header.DataLength = FDCAN_DLC_BYTES_2;
214 tx_header.DataLength = FDCAN_DLC_BYTES_3;
217 tx_header.DataLength = FDCAN_DLC_BYTES_4;
220 tx_header.DataLength = FDCAN_DLC_BYTES_5;
223 tx_header.DataLength = FDCAN_DLC_BYTES_6;
226 tx_header.DataLength = FDCAN_DLC_BYTES_7;
229 tx_header.DataLength = FDCAN_DLC_BYTES_8;
232 tx_header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
233 tx_header.BitRateSwitch = FDCAN_BRS_OFF;
234 tx_header.FDFormat = FDCAN_CLASSIC_CAN;
235 tx_header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
236 tx_header.MessageMarker = 0;
240 static inline void update_rx_message(
CanMessage &msg,
241 const FDCAN_RxHeaderTypeDef &rx_header) {
242 msg.id = rx_header.Identifier;
243 if (rx_header.IdType == FDCAN_STANDARD_ID) {
245 }
else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
248 switch (rx_header.DataLength) {
249 case FDCAN_DLC_BYTES_0:
252 case FDCAN_DLC_BYTES_1:
255 case FDCAN_DLC_BYTES_2:
258 case FDCAN_DLC_BYTES_3:
261 case FDCAN_DLC_BYTES_4:
264 case FDCAN_DLC_BYTES_5:
267 case FDCAN_DLC_BYTES_6:
270 case FDCAN_DLC_BYTES_7:
273 case FDCAN_DLC_BYTES_8: