libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
stm32_usb_dev.cpp
1#include "stm32_usb_dev.hpp"
2
3#include "stm32_dcache.hpp"
4#if defined(HAL_PCD_MODULE_ENABLED)
5
6using namespace LibXR;
7
8stm32_usb_dev_id_t STM32USBDeviceGetID(PCD_HandleTypeDef* hpcd)
9{
10 for (int i = 0; i < STM32_USB_DEV_ID_NUM; i++)
11 {
12 if (STM32USBDevice::map_[i] && STM32USBDevice::map_[i]->hpcd_ == hpcd)
13 {
14 return static_cast<stm32_usb_dev_id_t>(i);
15 }
16 }
17 return STM32_USB_DEV_ID_NUM;
18}
19
20extern "C" void HAL_PCD_SOFCallback(PCD_HandleTypeDef* hpcd) { UNUSED(hpcd); }
21
22extern "C" void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef* hpcd)
23{
24 auto id = STM32USBDeviceGetID(hpcd);
25
26 if (id >= STM32_USB_DEV_ID_NUM)
27 {
28 return;
29 }
30
31 auto usb = STM32USBDevice::map_[id];
32
33 if (!usb)
34 {
35 return;
36 }
37
38 if (STM32USBUsesDma(hpcd))
39 {
41 }
42
43 usb->GetEndpoint0In()->SetState(USB::Endpoint::State::IDLE);
44 usb->GetEndpoint0Out()->SetState(USB::Endpoint::State::IDLE);
45
46 usb->OnSetupPacket(true, reinterpret_cast<USB::SetupPacket*>(hpcd->Setup));
47}
48
49extern "C" void HAL_PCD_ResetCallback(PCD_HandleTypeDef* hpcd)
50{
51 auto id = STM32USBDeviceGetID(hpcd);
52
53 if (id >= STM32_USB_DEV_ID_NUM)
54 {
55 return;
56 }
57
58 auto usb = STM32USBDevice::map_[id];
59
60 if (!usb)
61 {
62 return;
63 }
64
65 usb->Deinit(true);
66 usb->Init(true);
67}
68
69extern "C" void HAL_PCD_SuspendCallback(PCD_HandleTypeDef* hpcd)
70{
71 auto id = STM32USBDeviceGetID(hpcd);
72
73 if (id >= STM32_USB_DEV_ID_NUM)
74 {
75 return;
76 }
77
78 auto usb = STM32USBDevice::map_[id];
79
80 if (!usb)
81 {
82 return;
83 }
84 usb->Deinit(true);
85}
86
87extern "C" void HAL_PCD_ResumeCallback(PCD_HandleTypeDef* hpcd)
88{
89 auto id = STM32USBDeviceGetID(hpcd);
90
91 if (id >= STM32_USB_DEV_ID_NUM)
92 {
93 return;
94 }
95
96 auto usb = STM32USBDevice::map_[id];
97
98 if (!usb)
99 {
100 return;
101 }
102 usb->Init(true);
103}
104
105extern "C" void HAL_PCD_ConnectCallback(PCD_HandleTypeDef* hpcd) { UNUSED(hpcd); }
106
107extern "C" void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef* hpcd) { UNUSED(hpcd); }
108
109#if (defined(USB_OTG_FS))
110
112 PCD_HandleTypeDef* hpcd, size_t rx_fifo_size,
113 const std::initializer_list<LibXR::RawData> RX_EP_CFGS,
114 const std::initializer_list<EPInConfig> TX_EP_CFGS,
115 USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid,
116 uint16_t bcd,
117 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
118 const std::initializer_list<const std::initializer_list<USB::ConfigDescriptorItem*>>
119 CONFIGS,
120 ConstRawData uid)
121 : STM32USBDevice(hpcd, STM32_USB_OTG_FS, RX_EP_CFGS.size() + TX_EP_CFGS.size(),
122 packet_size, vid, pid, bcd, LANG_LIST, CONFIGS, uid)
123{
124 ASSERT(RX_EP_CFGS.size() > 0 && RX_EP_CFGS.size() <= STM32Endpoint::EP_OTG_FS_MAX_SIZE);
125 ASSERT(TX_EP_CFGS.size() > 0 && TX_EP_CFGS.size() <= STM32Endpoint::EP_OTG_FS_MAX_SIZE);
126 ASSERT(64 * RX_EP_CFGS.size() <= rx_fifo_size);
127
128 auto rx_cfgs_itr = RX_EP_CFGS.begin();
129 auto tx_cfgs_itr = TX_EP_CFGS.begin();
130
131 // EP0 OUT 先设置 GRXFSIZ;HAL_PCDEx_SetTxFiFo(0) 以 GRXFSIZ 作为 TX0 起始地址。
132 // EP0 OUT sets GRXFSIZ first; HAL_PCDEx_SetTxFiFo(0) uses GRXFSIZ as the TX0 start.
133 auto ep0_out =
135 USB::Endpoint::Direction::OUT, rx_fifo_size, (*rx_cfgs_itr));
136
137 auto ep0_in = new STM32Endpoint(USB::Endpoint::EPNumber::EP0, id_, hpcd_,
138 USB::Endpoint::Direction::IN, (*tx_cfgs_itr).fifo_size,
139 (*tx_cfgs_itr).buffer);
140
141 USB::EndpointPool::SetEndpoint0(ep0_in, ep0_out);
142
143 rx_cfgs_itr++;
144 tx_cfgs_itr++;
145
147
148 size_t fifo_used_size = rx_fifo_size;
149
150 for (; rx_cfgs_itr != RX_EP_CFGS.end(); rx_cfgs_itr++)
151 {
152 auto ep = new STM32Endpoint(rx_ep_index, id_, hpcd_, USB::Endpoint::Direction::OUT,
153 rx_fifo_size, (*rx_cfgs_itr));
155 rx_ep_index = USB::Endpoint::NextEPNumber(rx_ep_index);
156 }
157
159
160 for (; tx_cfgs_itr != TX_EP_CFGS.end(); tx_cfgs_itr++)
161 {
162 auto ep = new STM32Endpoint(tx_ep_index, id_, hpcd_, USB::Endpoint::Direction::IN,
163 (*tx_cfgs_itr).fifo_size, (*tx_cfgs_itr).buffer);
165 tx_ep_index = USB::Endpoint::NextEPNumber(tx_ep_index);
166 fifo_used_size += (*tx_cfgs_itr).fifo_size;
167 }
168
169 if (fifo_used_size > USB_OTG_FS_TOTAL_FIFO_SIZE)
170 {
171 ASSERT(false);
172 }
173}
174
177{
178 HAL_StatusTypeDef ans = HAL_OK;
179
181 {
182 ans = HAL_PCD_SetAddress(hpcd_, address);
183 }
184 return (ans == HAL_OK) ? ErrorCode::OK : ErrorCode::FAILED;
185}
186
187#endif
188
189#if (defined(USB_OTG_HS))
190
192 PCD_HandleTypeDef* hpcd, size_t rx_fifo_size,
193 const std::initializer_list<LibXR::RawData> RX_EP_CFGS,
194 const std::initializer_list<EPInConfig> TX_EP_CFGS,
195 USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid,
196 uint16_t bcd,
197 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
198 const std::initializer_list<const std::initializer_list<USB::ConfigDescriptorItem*>>
199 CONFIGS,
200 ConstRawData uid)
202 hpcd, STM32_USB_OTG_HS, RX_EP_CFGS.size() + TX_EP_CFGS.size(), packet_size, vid,
203 pid, bcd, LANG_LIST, CONFIGS, uid,
204 hpcd->Init.speed == PCD_SPEED_HIGH ? USB::Speed::HIGH : USB::Speed::FULL)
205{
206 ASSERT(RX_EP_CFGS.size() > 0 && RX_EP_CFGS.size() <= STM32Endpoint::EP_OTG_HS_MAX_SIZE);
207 ASSERT(TX_EP_CFGS.size() > 0 && TX_EP_CFGS.size() <= STM32Endpoint::EP_OTG_HS_MAX_SIZE);
208 ASSERT(64 * RX_EP_CFGS.size() <= rx_fifo_size);
209
210 auto rx_cfgs_itr = RX_EP_CFGS.begin();
211 auto tx_cfgs_itr = TX_EP_CFGS.begin();
212
213 // EP0 OUT 先设置 GRXFSIZ;HAL_PCDEx_SetTxFiFo(0) 以 GRXFSIZ 作为 TX0 起始地址。
214 // EP0 OUT sets GRXFSIZ first; HAL_PCDEx_SetTxFiFo(0) uses GRXFSIZ as the TX0 start.
215 auto ep0_out =
217 USB::Endpoint::Direction::OUT, rx_fifo_size, (*rx_cfgs_itr));
218
219 auto ep0_in = new STM32Endpoint(USB::Endpoint::EPNumber::EP0, id_, hpcd_,
220 USB::Endpoint::Direction::IN, (*tx_cfgs_itr).fifo_size,
221 (*tx_cfgs_itr).buffer);
222
223 USB::EndpointPool::SetEndpoint0(ep0_in, ep0_out);
224
225 rx_cfgs_itr++;
226 tx_cfgs_itr++;
227
229
230 size_t fifo_used_size = rx_fifo_size;
231
232 for (; rx_cfgs_itr != RX_EP_CFGS.end(); rx_cfgs_itr++)
233 {
234 auto ep = new STM32Endpoint(rx_ep_index, id_, hpcd_, USB::Endpoint::Direction::OUT,
235 rx_fifo_size, (*rx_cfgs_itr));
237 rx_ep_index = USB::Endpoint::NextEPNumber(rx_ep_index);
238 }
239
241
242 for (; tx_cfgs_itr != TX_EP_CFGS.end(); tx_cfgs_itr++)
243 {
244 auto ep = new STM32Endpoint(tx_ep_index, id_, hpcd_, USB::Endpoint::Direction::IN,
245 (*tx_cfgs_itr).fifo_size, (*tx_cfgs_itr).buffer);
247 tx_ep_index = USB::Endpoint::NextEPNumber(tx_ep_index);
248 fifo_used_size += (*tx_cfgs_itr).fifo_size;
249 }
250
251 if (fifo_used_size > USB_OTG_HS_TOTAL_FIFO_SIZE)
252 {
253 ASSERT(false);
254 }
255}
256
259{
260 HAL_StatusTypeDef ans = HAL_OK;
261
263 {
264 ans = HAL_PCD_SetAddress(hpcd_, address);
265 }
266 return (ans == HAL_OK) ? ErrorCode::OK : ErrorCode::FAILED;
267}
268
269#endif
270
271#if defined(USB_BASE) || defined(USB_DRD_FS)
272STM32USBDeviceDevFs::STM32USBDeviceDevFs(
273 PCD_HandleTypeDef* hpcd, const std::initializer_list<EPConfig> EP_CFGS,
274 USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid,
275 uint16_t bcd,
276 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
277 const std::initializer_list<const std::initializer_list<USB::ConfigDescriptorItem*>>
278 CONFIGS,
279 ConstRawData uid)
280 : STM32USBDevice(hpcd, STM32_USB_FS_DEV, EP_CFGS.size() * 2, packet_size, vid, pid,
281 bcd, LANG_LIST, CONFIGS, uid)
282{
283 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= hpcd->Init.dev_endpoints);
284
285 auto cfgs_itr = EP_CFGS.begin();
286
287#if defined(PMA_START_ADDR)
288 size_t buffer_offset = PMA_START_ADDR;
289#else
290 size_t buffer_offset = BTABLE_ADDRESS + hpcd_->Init.dev_endpoints * 8U; // 字节
291#endif
292
293 auto ep0_out = new STM32Endpoint(USB::Endpoint::EPNumber::EP0, id_, hpcd_,
294 USB::Endpoint::Direction::OUT, buffer_offset,
295 (*cfgs_itr).hw_buffer_size2, (*cfgs_itr).buffer2);
296
297 buffer_offset += (*cfgs_itr).hw_buffer_size2;
298
299 auto ep0_in = new STM32Endpoint(USB::Endpoint::EPNumber::EP0, id_, hpcd_,
300 USB::Endpoint::Direction::IN, buffer_offset,
301 (*cfgs_itr).hw_buffer_size1, (*cfgs_itr).buffer1);
302
303 buffer_offset += (*cfgs_itr).hw_buffer_size1;
304
305 USB::EndpointPool::SetEndpoint0(ep0_in, ep0_out);
306
307 cfgs_itr++;
308
310
311 while (cfgs_itr != EP_CFGS.end())
312 {
313 if (cfgs_itr->hw_buffer_size2 == 0)
314 {
315 ASSERT(cfgs_itr->buffer1.size_ % 2 == 0);
316 auto ep = new STM32Endpoint(
317 ep_index, id_, hpcd_,
318 cfgs_itr->double_buffer_is_in ? USB::Endpoint::Direction::IN
320 buffer_offset, (*cfgs_itr).hw_buffer_size1, (*cfgs_itr).buffer1);
322 ep_index = USB::Endpoint::NextEPNumber(ep_index);
323 buffer_offset += (*cfgs_itr).hw_buffer_size1;
324 cfgs_itr++;
325 }
326 else
327 {
328 ASSERT(cfgs_itr->buffer1.size_ % 2 == 0);
329 ASSERT(cfgs_itr->buffer2.size_ % 2 == 0);
330
331 auto ep_in = new STM32Endpoint(ep_index, id_, hpcd_, USB::Endpoint::Direction::IN,
332 buffer_offset, (*cfgs_itr).hw_buffer_size1,
333 (*cfgs_itr).buffer1);
335 buffer_offset += (*cfgs_itr).hw_buffer_size1;
336 auto ep_out = new STM32Endpoint(ep_index, id_, hpcd_, USB::Endpoint::Direction::OUT,
337 buffer_offset, (*cfgs_itr).hw_buffer_size2,
338 (*cfgs_itr).buffer2);
340 buffer_offset += (*cfgs_itr).hw_buffer_size2;
341 ep_index = USB::Endpoint::NextEPNumber(ep_index);
342 cfgs_itr++;
343 }
344 }
345
346 ASSERT(USB::Endpoint::EPNumberToInt8(ep_index) < hpcd->Init.dev_endpoints);
347 ASSERT(buffer_offset <= LIBXR_STM32_USB_PMA_SIZE);
348}
349
350ErrorCode STM32USBDeviceDevFs::SetAddress(uint8_t address,
352{
353 HAL_StatusTypeDef ans = HAL_OK;
354
356 {
357 ans = HAL_PCD_SetAddress(hpcd_, address);
358 }
359 return (ans == HAL_OK) ? ErrorCode::OK : ErrorCode::FAILED;
360}
361#endif
362
363#endif
只读原始数据视图 / Immutable raw data view
STM32 USB 端点实现 / STM32 USB endpoint implementation.
STM32 USB 设备核心实现 / STM32 USB device core implementation.
STM32USBDeviceOtgFS(PCD_HandleTypeDef *hpcd, size_t rx_fifo_size, const std::initializer_list< LibXR::RawData > RX_EP_CFGS, const std::initializer_list< EPInConfig > TX_EP_CFGS, USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid, uint16_t bcd, const std::initializer_list< const USB::DescriptorStrings::LanguagePack * > LANG_LIST, const std::initializer_list< const std::initializer_list< USB::ConfigDescriptorItem * > > CONFIGS, ConstRawData uid={nullptr, 0})
构造 OTG FS 设备对象 / Construct OTG FS device object
ErrorCode SetAddress(uint8_t address, USB::DeviceCore::Context context) override
设置设备地址(由子类实现) Set device address (implemented by derived class).
STM32USBDeviceOtgHS(PCD_HandleTypeDef *hpcd, size_t rx_fifo_size, const std::initializer_list< LibXR::RawData > RX_EP_CFGS, const std::initializer_list< EPInConfig > TX_EP_CFGS, USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid, uint16_t bcd, const std::initializer_list< const USB::DescriptorStrings::LanguagePack * > LANG_LIST, const std::initializer_list< const std::initializer_list< USB::ConfigDescriptorItem * > > CONFIGS, ConstRawData uid={nullptr, 0})
构造 OTG HS 设备对象 / Construct OTG HS device object
ErrorCode SetAddress(uint8_t address, USB::DeviceCore::Context context) override
设置设备地址(由子类实现) Set device address (implemented by derived class).
Context
控制传输上下文 / Control transfer context
Definition dev_core.hpp:31
@ STATUS_IN_ARMED
STATUS IN ZLP armed, but not yet completed.
Definition dev_core.hpp:34
@ STATUS_IN_COMPLETE
IN status stage completed.
Definition dev_core.hpp:38
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
Definition desc_dev.hpp:74
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
@ EP0
端点 0 / Endpoint 0
@ EP1
端点 1 / Endpoint 1
static constexpr uint8_t EPNumberToInt8(EPNumber ep)
端点号转换为 uint8_t / Convert endpoint number to uint8_t
Definition ep.hpp:93
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
static constexpr EPNumber NextEPNumber(EPNumber ep)
获取下一个端点号 / Get the next endpoint number
Definition ep.hpp:127
ErrorCode Put(Endpoint *ep)
登记一个端点到池中 / Register an endpoint into the pool
Definition ep_pool.cpp:7
void SetEndpoint0(Endpoint *ep0_in, Endpoint *ep0_out)
设置端点0的IN/OUT对象 / Set Endpoint 0 IN/OUT objects
Definition ep_pool.cpp:160
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ FAILED
操作失败 / Operation failed
@ FULL
已满 / Full
@ OK
操作成功 / Operation successful
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)
Definition core.hpp:59