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)
10STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t id,
11 PCD_HandleTypeDef* hpcd, Direction dir, size_t fifo_size,
12 LibXR::RawData buffer)
13 : Endpoint(ep_num, dir, buffer), hpcd_(hpcd), fifo_size_(fifo_size), id_(id)
14{
15 ASSERT(fifo_size >= 8);
16 ASSERT(is_power_of_two(fifo_size) || fifo_size % 64 == 0);
17 ASSERT(is_power_of_two(buffer.size_) || buffer.size_ % 64 == 0);
18
19#if defined(USB_OTG_HS)
20 if (id == STM32_USB_OTG_HS)
21 {
22 map_hs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
23 }
24#endif
25#if defined(USB_OTG_FS)
26 if (id == STM32_USB_OTG_FS)
27 {
28 map_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
29 }
30#endif
31
32 if (dir == Direction::IN)
33 {
34 HAL_PCDEx_SetTxFiFo(hpcd_, EPNumberToInt8(GetNumber()), fifo_size / 4);
35 }
36 else if (dir == Direction::OUT && ep_num == USB::Endpoint::EPNumber::EP0)
37 {
38 HAL_PCDEx_SetRxFiFo(hpcd_, fifo_size / 4);
39 }
40}
41#endif
42
43#if defined(USB_BASE)
44STM32Endpoint::STM32Endpoint(EPNumber ep_num, stm32_usb_dev_id_t id,
45 PCD_HandleTypeDef* hpcd, Direction dir,
46 size_t hw_buffer_offset, size_t hw_buffer_size,
47 bool double_hw_buffer, LibXR::RawData buffer)
48 : Endpoint(ep_num, dir, buffer),
49 hpcd_(hpcd),
50 hw_buffer_size_(hw_buffer_size),
51 double_hw_buffer_(double_hw_buffer),
52 id_(id)
53{
54 ASSERT(hw_buffer_size >= 8);
55
56 ASSERT(is_power_of_two(hw_buffer_size));
57 ASSERT(is_power_of_two(buffer.size_) || buffer.size_ % 64 == 0);
58
59 map_otg_fs_[EPNumberToInt8(GetNumber())][static_cast<uint8_t>(dir)] = this;
60
61 size_t buffer_offset = hw_buffer_offset;
62
63 if (double_hw_buffer)
64 {
65 buffer_offset |= ((hw_buffer_offset + hw_buffer_size) << 16);
66 }
67
68 HAL_PCDEx_PMAConfig(hpcd_, EPNumberToAddr(GetNumber(), dir),
69 double_hw_buffer ? PCD_DBL_BUF : PCD_SNG_BUF, buffer_offset);
70}
71#endif
72
74{
75 ASSERT(cfg.direction == Direction::IN || cfg.direction == Direction::OUT);
76
77 uint8_t addr = EPNumberToAddr(GetNumber(), cfg.direction);
78 uint8_t type = static_cast<uint8_t>(cfg.type);
79 auto& ep_cfg = GetConfig();
80 size_t packet_size_limit = 0;
81
82 ep_cfg = cfg;
83
84 switch (cfg.type)
85 {
86 case Type::BULK:
87#if defined(PCD_SPEED_HIGH_IN_FULL)
88 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
89 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
90#else
91 if (hpcd_->Init.speed == PCD_SPEED_FULL)
92#endif
93 {
94 packet_size_limit = 64;
95 }
96 else
97 {
98 packet_size_limit = 512;
99 }
100 break;
101 case Type::INTERRUPT:
102#if defined(PCD_SPEED_HIGH_IN_FULL)
103 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
104 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
105#else
106 if (hpcd_->Init.speed == PCD_SPEED_FULL)
107#endif
108 {
109 packet_size_limit = 64;
110 }
111 else
112 {
113 packet_size_limit = 1024;
114 }
115 break;
117#if defined(PCD_SPEED_HIGH_IN_FULL)
118 if (hpcd_->Init.speed == PCD_SPEED_FULL ||
119 hpcd_->Init.speed == PCD_SPEED_HIGH_IN_FULL)
120#else
121 if (hpcd_->Init.speed == PCD_SPEED_FULL)
122#endif
123 {
124 packet_size_limit = 1023;
125 }
126 else
127 {
128 packet_size_limit = 1024;
129 }
130 break;
131 case Type::CONTROL:
132 packet_size_limit = 64;
133 break;
134 default:
135 break;
136 }
137
138#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
139 if (packet_size_limit > fifo_size_)
140 {
141 packet_size_limit = fifo_size_;
142 }
143#endif
144
145#if defined(USB_BASE)
146 if (packet_size_limit > hw_buffer_size_)
147 {
148 packet_size_limit = hw_buffer_size_;
149 }
150#endif
151
152 auto buffer = GetBuffer();
153
154 if (packet_size_limit > buffer.size_)
155 {
156 packet_size_limit = buffer.size_;
157 }
158
159 size_t max_packet_size = cfg.max_packet_size;
160
161 if (max_packet_size > packet_size_limit)
162 {
163 max_packet_size = packet_size_limit;
164 }
165
166 ep_cfg.max_packet_size = max_packet_size;
167
168 if (max_packet_size < 8)
169 {
170 max_packet_size = 8;
171 }
172
173 if (HAL_PCD_EP_Open(hpcd_, addr, max_packet_size, type) == HAL_OK)
174 {
176 }
177 else
178 {
180 }
181}
182
184{
185 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
186 HAL_PCD_EP_Close(hpcd_, addr);
188}
189
190ErrorCode STM32Endpoint::Transfer(size_t size)
191{
192 if (GetState() == State::BUSY)
193 {
194 return ErrorCode::BUSY;
195 }
196
197 bool is_in = GetDirection() == Direction::IN;
198 auto ep_addr = EPNumberToAddr(GetNumber(), GetDirection());
199
200 PCD_EPTypeDef* ep = is_in ? &hpcd_->IN_ep[ep_addr & EP_ADDR_MSK]
201 : &hpcd_->OUT_ep[ep_addr & EP_ADDR_MSK];
202
203 auto buffer = GetBuffer();
204
205 if (buffer.size_ < size)
206 {
207 return ErrorCode::NO_BUFF;
208 }
209
210 ep->xfer_buff = reinterpret_cast<uint8_t*>(buffer.addr_);
211
212 if (UseDoubleBuffer() && GetDirection() == Direction::IN && size > 0)
213 {
214 SwitchBuffer();
215 }
216
217 ep->xfer_len = size;
218 ep->xfer_count = 0U;
219 ep->is_in = is_in ? 1U : 0U;
220 ep->num = ep_addr & EP_ADDR_MSK;
221
222#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
223 if (hpcd_->Init.dma_enable == 1U)
224 {
225 ep->dma_addr = reinterpret_cast<uint32_t>(ep->xfer_buff);
226
227#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
228 if (is_in == true)
229 {
230 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t*>(buffer.addr_),
231 static_cast<int32_t>(size));
232 }
233#endif
234 }
235#endif
236
237#if defined(USB_BASE)
238 if (is_in)
239 {
240 ep->xfer_fill_db = 1U;
241 ep->xfer_len_db = size;
242 }
243#endif
244
246
247#if defined(USB_OTG_FS) || defined(USB_OTG_HS)
248 auto ans = USB_EPStartXfer(hpcd_->Instance, ep, hpcd_->Init.dma_enable);
249#else
250 auto ans = USB_EPStartXfer(hpcd_->Instance, ep);
251 if (size == 0 && GetNumber() == USB::Endpoint::EPNumber::EP0 &&
253 {
254 OnTransferCompleteCallback(false, 0);
255 }
256#endif
257
258 if (ans == HAL_OK)
259 {
260 return ErrorCode::OK;
261 }
262 else
263 {
265 return ErrorCode::FAILED;
266 }
267}
268
270{
271 if (GetState() != State::IDLE)
272 {
273 return ErrorCode::BUSY;
274 }
275
276 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
277 if (HAL_PCD_EP_SetStall(hpcd_, addr) == HAL_OK)
278 {
280 return ErrorCode::OK;
281 }
282 else
283 {
285 return ErrorCode::FAILED;
286 }
287}
288
290{
291 if (GetState() != State::STALLED)
292 {
293 return ErrorCode::FAILED;
294 }
295
296 uint8_t addr = EPNumberToAddr(GetNumber(), GetDirection());
297
299 {
301 return ErrorCode::OK;
302 }
303
304 if (HAL_PCD_EP_ClrStall(hpcd_, addr) == HAL_OK)
305 {
307 return ErrorCode::OK;
308 }
309 else
310 {
312 return ErrorCode::FAILED;
313 }
314}
315
317{
319 {
320 return MaxPacketSize();
321 }
322 else
323 {
324 return GetBuffer().size_;
325 }
326}
327
328// --- HAL C 回调桥接 ---
329// NOLINTNEXTLINE
330static STM32Endpoint* GetEndpoint(PCD_HandleTypeDef* hpcd, uint8_t epnum, bool is_in)
331{
332 auto id = STM32USBDeviceGetID(hpcd);
333#if defined(USB_OTG_HS)
334 if (id == STM32_USB_OTG_HS)
335 {
336 return STM32Endpoint::map_hs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
337 }
338#endif
339#if defined(USB_OTG_FS)
340 if (id == STM32_USB_OTG_FS)
341 {
342 return STM32Endpoint::map_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
343 }
344#endif
345#if defined(USB_BASE)
346 if (id == STM32_USB_FS_DEV)
347 {
348 return STM32Endpoint::map_otg_fs_[epnum & 0x7F][static_cast<uint8_t>(is_in)];
349 }
350#endif
351 return nullptr;
352}
353
354extern "C" void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
355{
356 auto id = STM32USBDeviceGetID(hpcd);
357
358 ASSERT(id < STM32_USB_DEV_ID_NUM);
359
360 auto ep = GetEndpoint(hpcd, epnum, true);
361
362 if (!ep || ep->hpcd_ != hpcd)
363 {
364 return;
365 }
366
367 PCD_EPTypeDef* ep_handle = &hpcd->IN_ep[epnum & EP_ADDR_MSK];
368
369 size_t actual_transfer_size = ep_handle->xfer_count;
370
371 ep->OnTransferCompleteCallback(true, actual_transfer_size);
372}
373
374extern "C" void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef* hpcd, uint8_t epnum)
375{
376 auto id = STM32USBDeviceGetID(hpcd);
377
378 ASSERT(id < STM32_USB_DEV_ID_NUM);
379
380 auto ep = GetEndpoint(hpcd, epnum, false);
381
382 if (!ep || ep->hpcd_ != hpcd)
383 {
384 return;
385 }
386
387 PCD_EPTypeDef* ep_handle = &hpcd->OUT_ep[epnum & EP_ADDR_MSK];
388
389 size_t actual_transfer_size = ep_handle->xfer_count;
390
391#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
392 SCB_InvalidateDCache_by_Addr(ep->GetBuffer().addr_,
393 static_cast<int32_t>(actual_transfer_size));
394#endif
395
396 ep->OnTransferCompleteCallback(true, actual_transfer_size);
397}
398
399#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 命名空间
Definition ch32_gpio.hpp:9
端点配置结构体 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