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