stm32rcos
読み取り中…
検索中…
一致する文字列を見つけられません
fdcan.hpp
[詳解]
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <iterator>
6#include <vector>
7
8#include <stm32cubemx_helper/context.hpp>
9#include <stm32cubemx_helper/device.hpp>
10
11#include "stm32rcos/core.hpp"
12
13#include "../can_base.hpp"
14#include "../can_filter.hpp"
15#include "../can_message.hpp"
16
17namespace stm32rcos {
18namespace peripheral {
19
20template <auto *Handle, class HandleType> class Can;
21
22template <auto *Handle>
23class Can<Handle, FDCAN_HandleTypeDef *> : public CanBase {
24public:
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;
32 static CanMessage msg;
33
34 auto fdcan = stm32cubemx_helper::get_context<Handle, Can>();
35
36 while (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rx_header,
37 msg.data.data()) == HAL_OK) {
38 if (rx_header.IsFilterMatchingFrame == 1) {
39 continue;
40 }
41 if (rx_header.IdType == FDCAN_STANDARD_ID) {
42 if (rx_header.FilterIndex >= fdcan->std_rx_queues_.size()) {
43 continue;
44 }
45 core::Queue<CanMessage> *rx_queue =
46 fdcan->std_rx_queues_[rx_header.FilterIndex];
47 if (rx_queue) {
48 update_rx_message(msg, rx_header);
49 rx_queue->push(msg, 0);
50 }
51 } else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
52 if (rx_header.FilterIndex >= fdcan->ext_rx_queues_.size()) {
53 continue;
54 }
55 core::Queue<CanMessage> *rx_queue =
56 fdcan->ext_rx_queues_[rx_header.FilterIndex];
57 if (rx_queue) {
58 update_rx_message(msg, rx_header);
59 rx_queue->push(msg, 0);
60 }
61 }
62 }
63 });
64 }
65
66 ~Can() override {
67 HAL_FDCAN_UnRegisterRxFifo0Callback(Handle);
68 stm32cubemx_helper::set_context<Handle, Can>(nullptr);
69 }
70
71 bool start() override {
72 if (HAL_FDCAN_ConfigGlobalFilter(Handle, FDCAN_REJECT, FDCAN_REJECT,
73 FDCAN_REJECT_REMOTE,
74 FDCAN_REJECT_REMOTE) != HAL_OK) {
75 return false;
76 }
77 if (HAL_FDCAN_ActivateNotification(Handle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
78 0) != HAL_OK) {
79 return false;
80 }
81 return HAL_FDCAN_Start(Handle) == HAL_OK;
82 }
83
84 bool stop() override {
85 if (HAL_FDCAN_Stop(Handle) != HAL_OK) {
86 return false;
87 }
88 return HAL_FDCAN_DeactivateNotification(
89 Handle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == HAL_OK;
90 }
91
92 bool transmit(const CanMessage &msg, uint32_t timeout) override {
93 FDCAN_TxHeaderTypeDef tx_header = create_tx_header(msg);
94 core::TimeoutHelper timeout_helper;
95 while (HAL_FDCAN_AddMessageToTxFifoQ(Handle, &tx_header, msg.data.data()) !=
96 HAL_OK) {
97 if (timeout_helper.is_timeout(timeout)) {
98 return false;
99 }
100 osDelay(1);
101 }
102 return true;
103 }
104
105 bool attach_rx_queue(const CanFilter &filter,
106 core::Queue<CanMessage> &queue) override {
107 if (filter.ide) {
108 size_t rx_queue_index = find_ext_rx_queue_index(nullptr);
109 if (rx_queue_index >= ext_rx_queues_.size()) {
110 return false;
111 }
112 FDCAN_FilterTypeDef filter_config =
113 create_filter_config(filter, rx_queue_index);
114 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
115 return false;
116 }
117 ext_rx_queues_[rx_queue_index] = &queue;
118 } else {
119 size_t rx_queue_index = find_std_rx_queue_index(nullptr);
120 if (rx_queue_index >= std_rx_queues_.size()) {
121 return false;
122 }
123 FDCAN_FilterTypeDef filter_config =
124 create_filter_config(filter, rx_queue_index);
125 if (HAL_FDCAN_ConfigFilter(Handle, &filter_config) != HAL_OK) {
126 return false;
127 }
128 std_rx_queues_[rx_queue_index] = &queue;
129 }
130 return true;
131 }
132
133 bool detach_rx_queue(const core::Queue<CanMessage> &queue) override {
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) {
140 return false;
141 }
142 std_rx_queues_[rx_queue_index] = nullptr;
143 } else {
144 rx_queue_index = find_ext_rx_queue_index(&queue);
145 if (rx_queue_index >= ext_rx_queues_.size()) {
146 return false;
147 }
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) {
152 return false;
153 }
154 ext_rx_queues_[rx_queue_index] = nullptr;
155 }
156 return true;
157 }
158
159private:
160 std::vector<core::Queue<CanMessage> *> std_rx_queues_{};
161 std::vector<core::Queue<CanMessage> *> ext_rx_queues_{};
162
163 Can(const Can &) = delete;
164 Can &operator=(const Can &) = delete;
165
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));
170 }
171
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));
176 }
177
178 static inline FDCAN_FilterTypeDef
179 create_filter_config(const CanFilter &filter, uint32_t filter_index) {
180 FDCAN_FilterTypeDef filter_config{};
181 if (filter.ide) {
182 filter_config.IdType = FDCAN_EXTENDED_ID;
183 } else {
184 filter_config.IdType = FDCAN_STANDARD_ID;
185 }
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;
192 }
193
194 static inline FDCAN_TxHeaderTypeDef create_tx_header(const CanMessage &msg) {
195 FDCAN_TxHeaderTypeDef tx_header{};
196 tx_header.Identifier = msg.id;
197 if (msg.ide) {
198 tx_header.IdType = FDCAN_EXTENDED_ID;
199 } else {
200 tx_header.IdType = FDCAN_STANDARD_ID;
201 }
202 tx_header.TxFrameType = FDCAN_DATA_FRAME;
203 switch (msg.dlc) {
204 case 0:
205 tx_header.DataLength = FDCAN_DLC_BYTES_0;
206 break;
207 case 1:
208 tx_header.DataLength = FDCAN_DLC_BYTES_1;
209 break;
210 case 2:
211 tx_header.DataLength = FDCAN_DLC_BYTES_2;
212 break;
213 case 3:
214 tx_header.DataLength = FDCAN_DLC_BYTES_3;
215 break;
216 case 4:
217 tx_header.DataLength = FDCAN_DLC_BYTES_4;
218 break;
219 case 5:
220 tx_header.DataLength = FDCAN_DLC_BYTES_5;
221 break;
222 case 6:
223 tx_header.DataLength = FDCAN_DLC_BYTES_6;
224 break;
225 case 7:
226 tx_header.DataLength = FDCAN_DLC_BYTES_7;
227 break;
228 case 8:
229 tx_header.DataLength = FDCAN_DLC_BYTES_8;
230 break;
231 }
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;
237 return tx_header;
238 }
239
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) {
244 msg.ide = false;
245 } else if (rx_header.IdType == FDCAN_EXTENDED_ID) {
246 msg.ide = true;
247 }
248 switch (rx_header.DataLength) {
249 case FDCAN_DLC_BYTES_0:
250 msg.dlc = 0;
251 break;
252 case FDCAN_DLC_BYTES_1:
253 msg.dlc = 1;
254 break;
255 case FDCAN_DLC_BYTES_2:
256 msg.dlc = 2;
257 break;
258 case FDCAN_DLC_BYTES_3:
259 msg.dlc = 3;
260 break;
261 case FDCAN_DLC_BYTES_4:
262 msg.dlc = 4;
263 break;
264 case FDCAN_DLC_BYTES_5:
265 msg.dlc = 5;
266 break;
267 case FDCAN_DLC_BYTES_6:
268 msg.dlc = 6;
269 break;
270 case FDCAN_DLC_BYTES_7:
271 msg.dlc = 7;
272 break;
273 case FDCAN_DLC_BYTES_8:
274 msg.dlc = 8;
275 break;
276 }
277 }
278};
279
280} // namespace peripheral
281} // namespace stm32rcos
Definition queue.hpp:14
bool push(const T &value, uint32_t timeout)
Definition queue.hpp:32
Definition utility.hpp:12
bool is_timeout(uint32_t &timeout)
Definition utility.hpp:16
Definition can_base.hpp:13
bool transmit(const CanMessage &msg, uint32_t timeout) override
Definition fdcan.hpp:92
bool start() override
Definition fdcan.hpp:71
bool attach_rx_queue(const CanFilter &filter, core::Queue< CanMessage > &queue) override
Definition fdcan.hpp:105
bool detach_rx_queue(const core::Queue< CanMessage > &queue) override
Definition fdcan.hpp:133
Definition can.hpp:78
Definition can.hpp:18
Definition mutex.hpp:9
Definition can_filter.hpp:8
bool ide
Definition can_filter.hpp:11
Definition can_message.hpp:9
std::array< uint8_t, 8 > data
Definition can_message.hpp:13