libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_usb_ep.cpp
1#include "stm32_usb_ep.hpp"
2
3using namespace LibXR;
4
5#if defined(HAL_PCD_MODULE_ENABLED)
6
7static inline bool is_power_of_two(unsigned int n) { return n > 0 && (n & (n - 1)) == 0; }
8
9#if defined(USB_OTG_HS) || defined(USB_OTG_FS)
10
11STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t id,
12 PCD_HandleTypeDef* hpcd, Direction dir, size_t fifo_size,
13 LibXR::RawData buffer)
14 : Endpoint(ep_num, dir, buffer), hpcd_(hpcd), fifo_size_(fifo_size), id_(id)
15{
16 ASSERT(fifo_size >= 8);
17 ASSERT(is_power_of_two(fifo_size) || fifo_size % 4 == 0);
18 ASSERT(is_power_of_two(buffer.size_) || buffer.size_ % 4 == 0);
19
20#if defined(USB_OTG_HS)
21 if (id == STM32_USB_OTG_HS)
22 {
23 map_otg_hs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
24 }
25#endif
26#if defined(USB_OTG_FS)
27 if (id == STM32_USB_OTG_FS)
28 {
29 map_otg_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
30 }
31#endif
32
33 if (dir == Direction::IN)
34 {
35 HAL_PCDEx_SetTxFiFo(hpcd_, EPNumberToInt8(GetNumber()), fifo_size / 4);
36 }
37 else if (dir == Direction::OUT && ep_num == USB::Endpoint::EPNumber::EP0)
38 {
39 HAL_PCDEx_SetRxFiFo(hpcd_, fifo_size / 4);
40 }
41}
42#endif
43
44#if defined(USB_BASE)
45STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t id,
46 PCD_HandleTypeDef* hpcd, Direction dir,
47 size_t hw_buffer_offset, size_t hw_buffer_size,
48 LibXR::RawData buffer)
49 : Endpoint(ep_num, dir, buffer), hpcd_(hpcd), hw_buffer_size_(hw_buffer_size), id_(id)
50{
51 ASSERT(hw_buffer_size >= 8);
52
53 ASSERT(is_power_of_two(hw_buffer_size));
54 ASSERT(is_power_of_two(buffer.size_) || buffer.size_ % 4 == 0);
55
56 map_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
57
58 size_t buffer_offset = hw_buffer_offset;
59
60 HAL_PCDEx_PMAConfig(hpcd_, EPNumberToAddr(GetNumber(), dir), PCD_SNG_BUF,
61 buffer_offset);
62}
63#endif
64
66{
67 ASSERT(cfg.direction == Direction::IN || cfg.direction == Direction::OUT);
68
69 uint8_t addr = EPNumberToAddr(GetNumber(), cfg.direction);
70 uint8_t type = static_cast<uint8_t>(cfg.type);
71 auto& ep_cfg = GetConfig();
72 size_t packet_size_limit = 0;
73
74 ep_cfg = cfg;
75
76 switch (cfg.type)
77 {
78 case Type::BULK:
79#if defined(PCD_SPEED_HIGH_IN_FULL)
80 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
81 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
82#else
83 if (hpcd_->Init.speed == PCD_SPEED_FULL)
84#endif
85 {
86 packet_size_limit = 64;
87 }
88 else
89 {
90 packet_size_limit = 512;
91 }
92 break;
93 case Type::INTERRUPT:
94#if defined(PCD_SPEED_HIGH_IN_FULL)
95 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
96 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
97#else
98 if (hpcd_->Init.speed == PCD_SPEED_FULL)
99#endif
100 {
101 packet_size_limit = 64;
102 }
103 else
104 {
105 packet_size_limit = 1024;
106 }
107 break;
109#if defined(PCD_SPEED_HIGH_IN_FULL)
110 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
111 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
112#else
113 if (hpcd_->Init.speed == PCD_SPEED_FULL)
114#endif
115 {
116 packet_size_limit = 1023;
117 }
118 else
119 {
120 packet_size_limit = 1024;
121 }
122 break;
123 case Type::CONTROL:
124 packet_size_limit = 64;
125 break;
126 default:
127 break;
128 }
129
130#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
131 if (packet_size_limit > fifo_size_)
132 {
133 packet_size_limit = fifo_size_;
134 }
135#endif
136
137#if defined(USB_BASE)
138 if (packet_size_limit > hw_buffer_size_)
139 {
140 packet_size_limit = hw_buffer_size_;
141 }
142#endif
143
144 auto buffer = GetBuffer();
145
146 if (packet_size_limit > buffer.size_)
147 {
148 packet_size_limit = buffer.size_;
149 }
150
151 size_t max_packet_size = cfg.max_packet_size;
152
153 if (max_packet_size > packet_size_limit)
154 {
155 max_packet_size = packet_size_limit;
156 }
157
158 ep_cfg.max_packet_size = max_packet_size;
159
160 if (max_packet_size < 8)
161 {
162 max_packet_size = 8;
163 }
164
165 if (HAL_PCD_EP_Open(hpcd_, addr, max_packet_size, type) == HAL_OK)
166 {
168 }
169 else
170 {
172 }
173}
174
176{
177 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
178 HAL_PCD_EP_Close(hpcd_, addr);
180}
181
182ErrorCode STM32Endpoint::Transfer(size_t size)
183{
184 if (GetState() == State::BUSY)
185 {
186 return ErrorCode::BUSY;
187 }
188
189 bool is_in = GetDirection() == Direction::IN;
190 auto ep_addr = EPNumberToAddr(GetNumber(), GetDirection());
191
192 PCD_EPTypeDef* ep = is_in ? &hpcd_->IN_ep[ep_addr & EP_ADDR_MSK]
193 : &hpcd_->OUT_ep[ep_addr & EP_ADDR_MSK];
194
195 auto buffer = GetBuffer();
196
197 if (buffer.size_ < size)
198 {
199 return ErrorCode::NO_BUFF;
200 }
201
202 ep->xfer_buff = reinterpret_cast<uint8_t*>(buffer.addr_);
203
204 if (UseDoubleBuffer() && GetDirection() == Direction::IN && size > 0)
205 {
206 SwitchBuffer();
207 }
208
209 ep->xfer_len = size;
210 ep->xfer_count = 0U;
211 ep->is_in = is_in ? 1U : 0U;
212 ep->num = ep_addr & EP_ADDR_MSK;
213 last_transfer_size_ = size;
214
215#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
216 if (hpcd_->Init.dma_enable == 1U)
217 {
218 ep->dma_addr = reinterpret_cast<uint32_t>(ep->xfer_buff);
219
220#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
221 if (is_in == true)
222 {
223 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t*>(buffer.addr_),
224 static_cast<int32_t>(size));
225 }
226#endif
227 }
228#endif
229
230#if defined(USB_BASE)
231 if (is_in)
232 {
233 ep->xfer_fill_db = 0U;
234 ep->xfer_len_db = 0U;
235 }
236#endif
237
239
240#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
241 auto ans = USB_EPStartXfer(hpcd_->Instance, ep, hpcd_->Init.dma_enable);
242#else
243 auto ans = USB_EPStartXfer(hpcd_->Instance, ep);
244 if (size == 0 && GetNumber() == USB::Endpoint::EPNumber::EP0 &&
246 {
248 }
249#endif
250
251 if (ans == HAL_OK)
252 {
253 return ErrorCode::OK;
254 }
255 else
256 {
258 return ErrorCode::FAILED;
259 }
260}
261
263{
264 if (GetState() != State::IDLE)
265 {
266 return ErrorCode::BUSY;
267 }
268
269 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
270 if (HAL_PCD_EP_SetStall(hpcd_, addr) == HAL_OK)
271 {
273 return ErrorCode::OK;
274 }
275 else
276 {
278 return ErrorCode::FAILED;
279 }
280}
281
283{
284 if (GetState() != State::STALLED)
285 {
286 return ErrorCode::FAILED;
287 }
288
289 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
290
292 {
294 return ErrorCode::OK;
295 }
296
297 if (HAL_PCD_EP_ClrStall(hpcd_, addr) == HAL_OK)
298 {
300 return ErrorCode::OK;
301 }
302 else
303 {
305 return ErrorCode::FAILED;
306 }
307}
308
310{
312 {
313 return MaxPacketSize();
314 }
315 else
316 {
317 return GetBuffer().size_;
318 }
319}
320
321// --- HAL C 回调桥接 ---
322// NOLINTNEXTLINE
323static STM32Endpoint* GetEndpoint(PCD_HandleTypeDef* hpcd, uint8_t epnum, bool is_in)
324{
325 auto id = STM32USBDeviceGetID(hpcd);
326#if defined(USB_OTG_HS)
327 if (id == STM32_USB_OTG_HS)
328 {
329 return STM32Endpoint::map_otg_hs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
330 }
331#endif
332#if defined(USB_OTG_FS)
333 if (id == STM32_USB_OTG_FS)
334 {
335 return STM32Endpoint::map_otg_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
336 }
337#endif
338#if defined(USB_BASE)
339 if (id == STM32_USB_FS_DEV)
340 {
341 return STM32Endpoint::map_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
342 }
343#endif
344 return nullptr;
345}
346
347extern "C" void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
348{
349 auto id = STM32USBDeviceGetID(hpcd);
350
351 ASSERT(id < STM32_USB_DEV_ID_NUM);
352
353 auto ep = GetEndpoint(hpcd, epnum, true);
354
355 if (!ep || ep->hpcd_ != hpcd)
356 {
357 return;
358 }
359
360 ep->OnTransferCompleteCallback(true, ep->last_transfer_size_);
361}
362
363extern "C" void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
364{
365 auto id = STM32USBDeviceGetID(hpcd);
366
367 ASSERT(id < STM32_USB_DEV_ID_NUM);
368
369 auto ep = GetEndpoint(hpcd, epnum, false);
370
371 if (!ep || ep->hpcd_ != hpcd)
372 {
373 return;
374 }
375
376 PCD_EPTypeDef* ep_handle = &hpcd->OUT_ep[epnum & EP_ADDR_MSK];
377
378 size_t actual_transfer_size = ep_handle->xfer_count;
379
380#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
381 SCB_InvalidateDCache_by_Addr(ep->GetBuffer().addr_,
382 static_cast<int32_t>(actual_transfer_size));
383#endif
384
385 ep->OnTransferCompleteCallback(true, actual_transfer_size);
386}
387
388extern "C" void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
389{
390 auto id = STM32USBDeviceGetID(hpcd);
391
392 ASSERT(id < STM32_USB_DEV_ID_NUM);
393
394 auto ep = GetEndpoint(hpcd, epnum, true);
395
396 if (!ep || ep->hpcd_ != hpcd)
397 {
398 return;
399 }
400
401 ep->OnTransferCompleteCallback(true, 0);
402}
403
404extern "C" void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
405{
406 auto id = STM32USBDeviceGetID(hpcd);
407
408 ASSERT(id < STM32_USB_DEV_ID_NUM);
409
410 auto ep = GetEndpoint(hpcd, epnum, false);
411
412 if (!ep || ep->hpcd_ != hpcd)
413 {
414 return;
415 }
416
417 ep->OnTransferCompleteCallback(true, 0);
418}
419#endif
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
STM32 USB 端点实现 / STM32 USB endpoint implementation.
ErrorCode Transfer(size_t size) override
启动一次传输 / Start a transfer
ErrorCode ClearStall() override
清除 STALL / Clear stall
void Configure(const Config &cfg) override
配置端点协议参数 / Configure endpoint protocol parameters
void Close() override
关闭端点 / Close endpoint
ErrorCode Stall() override
置 STALL / Stall endpoint
size_t MaxTransferSize() const override
返回当前最大可传输字节数 / Return maximum transferable size at this time
@ EP0
端点 0 / Endpoint 0
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
static constexpr uint8_t EPNumberToAddr(EPNumber ep, Direction dir)
端点号转换为端点地址 / Convert endpoint number to endpoint address
Definition ep.hpp:104
Direction GetDirection() const
获取当前端点方向 / Get current endpoint direction
Definition ep.hpp:181
bool UseDoubleBuffer() const
是否启用双缓冲 / Whether double buffer is enabled
Definition ep.hpp:239
virtual void SwitchBuffer()
切换双缓冲 / Switch double buffer
Definition ep.hpp:520
Config & GetConfig()
获取当前配置引用 / Get endpoint config reference
Definition ep.hpp:515
void OnTransferCompleteCallback(bool in_isr, size_t actual_transfer_size)
由底层在传输完成时调用 / Called by low-level driver when transfer completes
Definition ep.hpp:392
@ ISOCHRONOUS
等时端点 / Isochronous
@ BULK
批量端点 / Bulk
@ INTERRUPT
中断端点 / Interrupt
@ CONTROL
控制端点 / Control
EPNumber GetNumber() const
获取端点号 / Get endpoint number
Definition ep.hpp:169
uint16_t MaxPacketSize() const
获取最大包长 / Get max packet size
Definition ep.hpp:225
@ DISABLED
禁用 / Disabled
@ STALLED
停止/挂起 / Stalled
void SetState(State state)
设置端点状态 / Set endpoint state
Definition ep.hpp:213
State GetState() const
获取端点状态 / Get endpoint state
Definition ep.hpp:207
RawData GetBuffer() const
获取当前可用于传输的缓冲区 / Get current transfer buffer
Definition ep.hpp:245
LibXR 命名空间
Definition ch32_can.hpp:14
端点配置参数 / Endpoint configuration parameters
Definition ep.hpp:138
Type type
端点类型 / Endpoint type
Definition ep.hpp:140
uint16_t max_packet_size
最大包长 / Max packet size
Definition ep.hpp:141
Direction direction
端点方向 / Endpoint direction
Definition ep.hpp:139