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_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_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 bool double_hw_buffer, LibXR::RawData buffer)
49 : Endpoint(ep_num, dir, buffer),
50 hpcd_(hpcd),
51 hw_buffer_size_(hw_buffer_size),
52 double_hw_buffer_(double_hw_buffer),
53 id_(id)
54{
55 ASSERT(hw_buffer_size >= 8);
56
57 ASSERT(is_power_of_two(hw_buffer_size));
58 ASSERT(is_power_of_two(buffer.size_) || buffer.size_ % 4 == 0);
59
60 map_otg_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
61
62 size_t buffer_offset = hw_buffer_offset;
63
64 if (double_hw_buffer)
65 {
66 buffer_offset |= ((hw_buffer_offset + hw_buffer_size) << 16);
67 }
68
69 HAL_PCDEx_PMAConfig(hpcd_, EPNumberToAddr(GetNumber(), dir),
70 double_hw_buffer ? PCD_DBL_BUF : PCD_SNG_BUF, buffer_offset);
71}
72#endif
73
75{
76 ASSERT(cfg.direction == Direction::IN || cfg.direction == Direction::OUT);
77
78 uint8_t addr = EPNumberToAddr(GetNumber(), cfg.direction);
79 uint8_t type = static_cast<uint8_t>(cfg.type);
80 auto& ep_cfg = GetConfig();
81 size_t packet_size_limit = 0;
82
83 ep_cfg = cfg;
84
85 switch (cfg.type)
86 {
87 case Type::BULK:
88#if defined(PCD_SPEED_HIGH_IN_FULL)
89 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
90 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
91#else
92 if (hpcd_->Init.speed == PCD_SPEED_FULL)
93#endif
94 {
95 packet_size_limit = 64;
96 }
97 else
98 {
99 packet_size_limit = 512;
100 }
101 break;
102 case Type::INTERRUPT:
103#if defined(PCD_SPEED_HIGH_IN_FULL)
104 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
105 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
106#else
107 if (hpcd_->Init.speed == PCD_SPEED_FULL)
108#endif
109 {
110 packet_size_limit = 64;
111 }
112 else
113 {
114 packet_size_limit = 1024;
115 }
116 break;
118#if defined(PCD_SPEED_HIGH_IN_FULL)
119 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
120 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
121#else
122 if (hpcd_->Init.speed == PCD_SPEED_FULL)
123#endif
124 {
125 packet_size_limit = 1023;
126 }
127 else
128 {
129 packet_size_limit = 1024;
130 }
131 break;
132 case Type::CONTROL:
133 packet_size_limit = 64;
134 break;
135 default:
136 break;
137 }
138
139#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
140 if (packet_size_limit > fifo_size_)
141 {
142 packet_size_limit = fifo_size_;
143 }
144#endif
145
146#if defined(USB_BASE)
147 if (packet_size_limit > hw_buffer_size_)
148 {
149 packet_size_limit = hw_buffer_size_;
150 }
151#endif
152
153 auto buffer = GetBuffer();
154
155 if (packet_size_limit > buffer.size_)
156 {
157 packet_size_limit = buffer.size_;
158 }
159
160 size_t max_packet_size = cfg.max_packet_size;
161
162 if (max_packet_size > packet_size_limit)
163 {
164 max_packet_size = packet_size_limit;
165 }
166
167 ep_cfg.max_packet_size = max_packet_size;
168
169 if (max_packet_size < 8)
170 {
171 max_packet_size = 8;
172 }
173
174 if (HAL_PCD_EP_Open(hpcd_, addr, max_packet_size, type) == HAL_OK)
175 {
177 }
178 else
179 {
181 }
182}
183
185{
186 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
187 HAL_PCD_EP_Close(hpcd_, addr);
189}
190
191ErrorCode STM32Endpoint::Transfer(size_t size)
192{
193 if (GetState() == State::BUSY)
194 {
195 return ErrorCode::BUSY;
196 }
197
198 bool is_in = GetDirection() == Direction::IN;
199 auto ep_addr = EPNumberToAddr(GetNumber(), GetDirection());
200
201 PCD_EPTypeDef* ep = is_in ? &hpcd_->IN_ep[ep_addr & EP_ADDR_MSK]
202 : &hpcd_->OUT_ep[ep_addr & EP_ADDR_MSK];
203
204 auto buffer = GetBuffer();
205
206 if (buffer.size_ < size)
207 {
208 return ErrorCode::NO_BUFF;
209 }
210
211 ep->xfer_buff = reinterpret_cast<uint8_t*>(buffer.addr_);
212
213 if (UseDoubleBuffer() && GetDirection() == Direction::IN && size > 0)
214 {
215 SwitchBuffer();
216 }
217
218 ep->xfer_len = size;
219 ep->xfer_count = 0U;
220 ep->is_in = is_in ? 1U : 0U;
221 ep->num = ep_addr & EP_ADDR_MSK;
222
223#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
224 if (hpcd_->Init.dma_enable == 1U)
225 {
226 ep->dma_addr = reinterpret_cast<uint32_t>(ep->xfer_buff);
227
228#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
229 if (is_in == true)
230 {
231 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t*>(buffer.addr_),
232 static_cast<int32_t>(size));
233 }
234#endif
235 }
236#endif
237
238#if defined(USB_BASE)
239 if (is_in)
240 {
241 ep->xfer_fill_db = 1U;
242 ep->xfer_len_db = size;
243 }
244#endif
245
247
248#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
249 auto ans = USB_EPStartXfer(hpcd_->Instance, ep, hpcd_->Init.dma_enable);
250#else
251 auto ans = USB_EPStartXfer(hpcd_->Instance, ep);
252 if (size == 0 && GetNumber() == USB::Endpoint::EPNumber::EP0 &&
254 {
255 OnTransferCompleteCallback(false, 0);
256 }
257#endif
258
259 if (ans == HAL_OK)
260 {
261 return ErrorCode::OK;
262 }
263 else
264 {
266 return ErrorCode::FAILED;
267 }
268}
269
271{
272 if (GetState() != State::IDLE)
273 {
274 return ErrorCode::BUSY;
275 }
276
277 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
278 if (HAL_PCD_EP_SetStall(hpcd_, addr) == HAL_OK)
279 {
281 return ErrorCode::OK;
282 }
283 else
284 {
286 return ErrorCode::FAILED;
287 }
288}
289
291{
292 if (GetState() != State::STALLED)
293 {
294 return ErrorCode::FAILED;
295 }
296
297 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
298
300 {
302 return ErrorCode::OK;
303 }
304
305 if (HAL_PCD_EP_ClrStall(hpcd_, addr) == HAL_OK)
306 {
308 return ErrorCode::OK;
309 }
310 else
311 {
313 return ErrorCode::FAILED;
314 }
315}
316
318{
320 {
321 return MaxPacketSize();
322 }
323 else
324 {
325 return GetBuffer().size_;
326 }
327}
328
329// --- HAL C 回调桥接 ---
330// NOLINTNEXTLINE
331static STM32Endpoint* GetEndpoint(PCD_HandleTypeDef* hpcd, uint8_t epnum, bool is_in)
332{
333 auto id = STM32USBDeviceGetID(hpcd);
334#if defined(USB_OTG_HS)
335 if (id == STM32_USB_OTG_HS)
336 {
337 return STM32Endpoint::map_hs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
338 }
339#endif
340#if defined(USB_OTG_FS)
341 if (id == STM32_USB_OTG_FS)
342 {
343 return STM32Endpoint::map_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
344 }
345#endif
346#if defined(USB_BASE)
347 if (id == STM32_USB_FS_DEV)
348 {
349 return STM32Endpoint::map_otg_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
350 }
351#endif
352 return nullptr;
353}
354
355extern "C" void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
356{
357 auto id = STM32USBDeviceGetID(hpcd);
358
359 ASSERT(id < STM32_USB_DEV_ID_NUM);
360
361 auto ep = GetEndpoint(hpcd, epnum, true);
362
363 if (!ep || ep->hpcd_ != hpcd)
364 {
365 return;
366 }
367
368 PCD_EPTypeDef* ep_handle = &hpcd->IN_ep[epnum & EP_ADDR_MSK];
369
370 size_t actual_transfer_size = ep_handle->xfer_count;
371
372 ep->OnTransferCompleteCallback(true, actual_transfer_size);
373}
374
375extern "C" void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
376{
377 auto id = STM32USBDeviceGetID(hpcd);
378
379 ASSERT(id < STM32_USB_DEV_ID_NUM);
380
381 auto ep = GetEndpoint(hpcd, epnum, false);
382
383 if (!ep || ep->hpcd_ != hpcd)
384 {
385 return;
386 }
387
388 PCD_EPTypeDef* ep_handle = &hpcd->OUT_ep[epnum & EP_ADDR_MSK];
389
390 size_t actual_transfer_size = ep_handle->xfer_count;
391
392#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
393 SCB_InvalidateDCache_by_Addr(ep->GetBuffer().addr_,
394 static_cast<int32_t>(actual_transfer_size));
395#endif
396
397 ep->OnTransferCompleteCallback(true, actual_transfer_size);
398}
399
400extern "C" void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
401{
402 auto id = STM32USBDeviceGetID(hpcd);
403
404 ASSERT(id < STM32_USB_DEV_ID_NUM);
405
406 auto ep = GetEndpoint(hpcd, epnum, true);
407
408 if (!ep || ep->hpcd_ != hpcd)
409 {
410 return;
411 }
412
413 ep->OnTransferCompleteCallback(true, 0);
414}
415
416extern "C" void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
417{
418 auto id = STM32USBDeviceGetID(hpcd);
419
420 ASSERT(id < STM32_USB_DEV_ID_NUM);
421
422 auto ep = GetEndpoint(hpcd, epnum, false);
423
424 if (!ep || ep->hpcd_ != hpcd)
425 {
426 return;
427 }
428
429 ep->OnTransferCompleteCallback(true, 0);
430}
431#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.
ErrorCode Transfer(size_t size) override
传输数据 Transfer data
ErrorCode ClearStall() override
清除端点停止状态 Clear endpoint stop status
void Configure(const Config &cfg) override
二次初始化/配置端点协议参数(由Pool/Manager分配后调用) Configure endpoint protocol parameters (call after pool allocation...
void Close() override
关闭端点(软禁用/资源复位) Close (soft disable)
ErrorCode Stall() override
停止端点传输 Stop endpoint transfer
size_t MaxTransferSize() const override
返回最大可传输字节数 Return the 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 endpoint direction
Definition ep.hpp:186
bool UseDoubleBuffer() const
是否使用双缓冲区 / Use double buffer
Definition ep.hpp:248
virtual void SwitchBuffer()
切换缓冲区 Switch buffer
Definition ep.hpp:372
Config & GetConfig()
获取当前配置 Get endpoint config
Definition ep.hpp:365
@ ISOCHRONOUS
等时端点 / Isochronous
@ BULK
批量端点 / Bulk
@ INTERRUPT
中断端点 / Interrupt
@ CONTROL
控制端点 / Control
EPNumber GetNumber() const
获取端点号 Get endpoint number
Definition ep.hpp:174
uint16_t MaxPacketSize() const
获取最大包长 Get max packet size
Definition ep.hpp:232
@ DISABLED
禁用 / Disabled
@ STALLED
挂起 / Stalled
void SetState(State state)
设置端点状态 Set endpoint state
Definition ep.hpp:220
State GetState() const
获取端点状态 Get endpoint state
Definition ep.hpp:212
RawData GetBuffer() const
获取端点缓冲区 Get endpoint buffer
Definition ep.hpp:256
LibXR 命名空间
端点配置结构体 Endpoint configuration struct
Definition ep.hpp:140
Type type
端点类型 / Endpoint type
Definition ep.hpp:142
uint16_t max_packet_size
最大包长 / Max packet size
Definition ep.hpp:143
Direction direction
端点方向 / Endpoint direction
Definition ep.hpp:141