stm32rcos
 
読み取り中…
検索中…
一致する文字列を見つけられません
bxcan.hpp
[詳解]
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cstdint>
6#include <iterator>
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<CAN_HandleTypeDef *> : public CanBase {
21public:
22 Can(CAN_HandleTypeDef *hcan) : hcan_{hcan} {
23 hal::set_bxcan_context(hcan_, this);
24 HAL_CAN_RegisterCallback(
25 hcan_, HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID, [](CAN_HandleTypeDef *hcan) {
26 static CAN_RxHeaderTypeDef rx_header;
27 static CanMessage msg;
28
29 auto bxcan = reinterpret_cast<Can *>(hal::get_bxcan_context(hcan));
30
31 while (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header,
32 msg.data.data()) == HAL_OK) {
33 if (rx_header.FilterMatchIndex >= Can::FILTER_BANK_SIZE) {
34 continue;
35 }
36 core::Queue<CanMessage> *rx_queue =
37 bxcan->rx_queues_[rx_header.FilterMatchIndex];
38 if (rx_queue) {
39 update_rx_message(msg, rx_header);
40 rx_queue->push(msg, 0);
41 }
42 }
43 });
44 }
45
46 ~Can() override {
47 HAL_CAN_UnRegisterCallback(hcan_, HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID);
48 hal::set_bxcan_context(hcan_, nullptr);
49 }
50
51 bool start() override {
52 if (HAL_CAN_ActivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING) !=
53 HAL_OK) {
54 return false;
55 }
56 return HAL_CAN_Start(hcan_) == HAL_OK;
57 }
58
59 bool stop() override {
60 if (HAL_CAN_Stop(hcan_) != HAL_OK) {
61 return false;
62 }
63 return HAL_CAN_DeactivateNotification(hcan_, CAN_IT_RX_FIFO0_MSG_PENDING) ==
64 HAL_OK;
65 }
66
67 bool transmit(const CanMessage &msg, uint32_t timeout) override {
68 CAN_TxHeaderTypeDef tx_header = create_tx_header(msg);
69 uint32_t tx_mailbox;
70 core::TimeoutHelper timeout_helper;
71 while (HAL_CAN_AddTxMessage(hcan_, &tx_header, msg.data.data(),
72 &tx_mailbox) != HAL_OK) {
73 if (timeout_helper.is_timeout(timeout)) {
74 return false;
75 }
76 osDelay(1);
77 }
78 return true;
79 }
80
81 bool attach_rx_queue(const CanFilter &filter,
82 core::Queue<CanMessage> &queue) override {
83 size_t rx_queue_index = find_rx_queue_index(nullptr);
84 if (rx_queue_index >= FILTER_BANK_SIZE) {
85 return false;
86 }
87 CAN_FilterTypeDef filter_config = create_filter_config(
88 filter, rx_queue_index_to_filter_index(hcan_, rx_queue_index));
89 if (HAL_CAN_ConfigFilter(hcan_, &filter_config) != HAL_OK) {
90 return false;
91 }
92 rx_queues_[rx_queue_index] = &queue;
93 return true;
94 }
95
96 bool detach_rx_queue(const core::Queue<CanMessage> &queue) override {
97 size_t rx_queue_index = find_rx_queue_index(&queue);
98 if (rx_queue_index >= FILTER_BANK_SIZE) {
99 return false;
100 }
101 CAN_FilterTypeDef filter_config{};
102 filter_config.FilterBank =
103 rx_queue_index_to_filter_index(hcan_, rx_queue_index);
104 filter_config.FilterActivation = DISABLE;
105 if (HAL_CAN_ConfigFilter(hcan_, &filter_config) != HAL_OK) {
106 return false;
107 }
108 rx_queues_[rx_queue_index] = nullptr;
109 return true;
110 }
111
112private:
113 static constexpr uint32_t FILTER_BANK_SIZE = 14;
114
115 CAN_HandleTypeDef *hcan_;
116 std::array<core::Queue<CanMessage> *, FILTER_BANK_SIZE> rx_queues_{};
117
118 Can(const Can &) = delete;
119 Can &operator=(const Can &) = delete;
120
121 size_t find_rx_queue_index(const core::Queue<CanMessage> *queue) {
122 return std::distance(
123 rx_queues_.begin(),
124 std::find(rx_queues_.begin(), rx_queues_.end(), queue));
125 }
126
127 static inline uint32_t
128 rx_queue_index_to_filter_index(const CAN_HandleTypeDef *hcan,
129 size_t rx_queue_index) {
130#ifdef CAN2
131 if (hcan->Instance == CAN2) {
132 return rx_queue_index + FILTER_BANK_SIZE;
133 }
134#endif
135 return rx_queue_index;
136 }
137
138 static inline CAN_FilterTypeDef create_filter_config(const CanFilter &filter,
139 uint32_t filter_index) {
140 CAN_FilterTypeDef filter_config{};
141 if (filter.ide) {
142 filter_config.FilterIdHigh = filter.id >> 13;
143 filter_config.FilterIdLow = ((filter.id << 3) & 0xFFFF) | 0x4;
144 filter_config.FilterMaskIdHigh = filter.mask >> 13;
145 filter_config.FilterMaskIdLow = ((filter.mask << 3) & 0xFFFF) | 0x4;
146 } else {
147 filter_config.FilterIdHigh = filter.id << 5;
148 filter_config.FilterIdLow = 0x0;
149 filter_config.FilterMaskIdHigh = filter.mask << 5;
150 filter_config.FilterMaskIdLow = 0x0;
151 }
152 filter_config.FilterFIFOAssignment = CAN_FILTER_FIFO0;
153 filter_config.FilterBank = filter_index;
154 filter_config.FilterMode = CAN_FILTERMODE_IDMASK;
155 filter_config.FilterScale = CAN_FILTERSCALE_32BIT;
156 filter_config.FilterActivation = ENABLE;
157 filter_config.SlaveStartFilterBank = FILTER_BANK_SIZE;
158 return filter_config;
159 }
160
161 static inline CAN_TxHeaderTypeDef create_tx_header(const CanMessage &msg) {
162 CAN_TxHeaderTypeDef tx_header{};
163 if (msg.ide) {
164 tx_header.ExtId = msg.id;
165 tx_header.IDE = CAN_ID_EXT;
166 } else {
167 tx_header.StdId = msg.id;
168 tx_header.IDE = CAN_ID_STD;
169 }
170 tx_header.RTR = CAN_RTR_DATA;
171 tx_header.DLC = msg.dlc;
172 tx_header.TransmitGlobalTime = DISABLE;
173 return tx_header;
174 }
175
176 static inline void update_rx_message(CanMessage &msg,
177 const CAN_RxHeaderTypeDef &rx_header) {
178 switch (rx_header.IDE) {
179 case CAN_ID_STD:
180 msg.id = rx_header.StdId;
181 msg.ide = false;
182 break;
183 case CAN_ID_EXT:
184 msg.id = rx_header.ExtId;
185 msg.ide = true;
186 break;
187 }
188 msg.dlc = rx_header.DLC;
189 }
190};
191
192} // namespace peripheral
193} // 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 bxcan.hpp:81
bool detach_rx_queue(const core::Queue< CanMessage > &queue) override
Definition bxcan.hpp:96
bool start() override
Definition bxcan.hpp:51
bool stop() override
Definition bxcan.hpp:59
~Can() override
Definition bxcan.hpp:46
bool transmit(const CanMessage &msg, uint32_t timeout) override
Definition bxcan.hpp:67
Can(CAN_HandleTypeDef *hcan)
Definition bxcan.hpp:22
Definition can.hpp:77
Definition can.hpp:18
Can(Handle) -> Can< Handle >
Definition mutex.hpp:9
Definition can_filter.hpp:8
Definition can_message.hpp:9
std::array< uint8_t, 8 > data
Definition can_message.hpp:13