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