libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_usbx.cpp
1#include "stm32_usbx.hpp"
2
3#if defined(HAL_PCD_MODULE_ENABLED) && defined(LIBXR_SYSTEM_ThreadX)
4
5#include "app_azure_rtos_config.h"
6#include "ux_device_descriptors.h"
7
8namespace LibXR
9{
10static uint8_t usbx_memory[UX_DEVICE_APP_MEM_POOL_SIZE];
11static UX_SLAVE_CLASS_CDC_ACM_PARAMETER cdc_acm_param;
12STM32VirtualUART *STM32VirtualUART::instance_ = nullptr;
13extern "C" void usbx_dcd_stm32_initialize(ULONG dcd_io, ULONG parameter);
14
15extern "C" void USBD_CDC_ACM_Activate(void *cdc_instance)
16{
17 if (STM32VirtualUART::instance_)
18 {
19 STM32VirtualUART::instance_->cdc_acm_ =
20 static_cast<UX_SLAVE_CLASS_CDC_ACM *>(cdc_instance);
21 }
22}
23
24extern "C" void USBD_CDC_ACM_Deactivate(void *cdc_instance)
25{
26 UNUSED(cdc_instance);
27 if (STM32VirtualUART::instance_)
28 {
29 STM32VirtualUART::instance_->cdc_acm_ = nullptr;
30 }
31}
32
33STM32VirtualUART::STM32VirtualUART(PCD_HandleTypeDef *hpcd, ULONG tx_stack_size,
34 UINT tx_priority, ULONG rx_stack_size,
35 UINT rx_priority, uint32_t tx_queue_size,
36 size_t buffer_size)
37 : UART(&_read_port, &_write_port),
38 tx_stack_size_(tx_stack_size),
39 rx_stack_size_(rx_stack_size),
40 tx_priority_(tx_priority),
41 rx_priority_(rx_priority),
42 buffer_size_(buffer_size),
43 rx_buff_(new uint8_t[buffer_size]),
44 tx_buff_(new uint8_t[buffer_size]),
45 write_sem_(0),
46 _read_port(buffer_size),
47 _write_port(tx_queue_size, buffer_size)
48{
49 // 初始化 USBX 协议栈
50 ux_system_initialize(usbx_memory, UX_DEVICE_APP_MEM_POOL_SIZE, UX_NULL, 0);
51
52 // 获取设备描述符/字符串/语言ID
53 ULONG fs_length, str_length, lang_length;
54 UCHAR *fs_desc = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED, &fs_length);
55 UCHAR *str_desc = USBD_Get_String_Framework(&str_length);
56 UCHAR *lang_desc = USBD_Get_Language_Id_Framework(&lang_length);
57
58 // 初始化 USB 设备栈
59 ux_device_stack_initialize(NULL, 0, fs_desc, fs_length, str_desc, str_length, lang_desc,
60 lang_length, NULL);
61
62 // 设置 CDC ACM 参数
63 cdc_acm_param.ux_slave_class_cdc_acm_instance_activate = USBD_CDC_ACM_Activate;
64 cdc_acm_param.ux_slave_class_cdc_acm_instance_deactivate = USBD_CDC_ACM_Deactivate;
65
66 // 注册 CDC ACM 类(interface 0, config 1)
67 ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name,
68 ux_device_class_cdc_acm_entry, 1, 0, &cdc_acm_param);
69
70 usbx_dcd_stm32_initialize(reinterpret_cast<ULONG>(hpcd->Instance),
71 reinterpret_cast<ULONG>(hpcd));
72
73 tx_stack_mem_ = new uint8_t[tx_stack_size_];
74 rx_stack_mem_ = new uint8_t[rx_stack_size_];
75
76 ASSERT(tx_stack_mem_ && rx_stack_mem_);
77
78 _read_port = ReadFun;
79 _write_port = WriteFun;
80
81 STM32VirtualUART::instance_ = this;
82
83 static CHAR thread_name_tx_[8] = "usbx_tx";
84 static CHAR thread_name_rx_[8] = "usbx_rx";
85
86 tx_thread_create(&tx_thread_, thread_name_tx_, &STM32VirtualUART::TxThreadEntry,
87 ULONG(this), tx_stack_mem_, tx_stack_size_, tx_priority_, tx_priority_,
88 TX_NO_TIME_SLICE, TX_AUTO_START);
89
90 tx_thread_create(&rx_thread_, thread_name_rx_, &STM32VirtualUART::RxThreadEntry,
91 ULONG(this), rx_stack_mem_, rx_stack_size_, rx_priority_, rx_priority_,
92 TX_NO_TIME_SLICE, TX_AUTO_START);
93
94 HAL_PCD_Start(hpcd);
95}
96
97STM32VirtualUART::~STM32VirtualUART()
98{
99 tx_thread_terminate(&tx_thread_);
100 tx_thread_delete(&tx_thread_);
101 tx_thread_terminate(&rx_thread_);
102 tx_thread_delete(&rx_thread_);
103
104 free(tx_stack_mem_);
105 free(rx_stack_mem_);
106 delete[] rx_buff_;
107 delete[] tx_buff_;
108}
109
110ErrorCode STM32VirtualUART::SetConfig(UART::Configuration config)
111{
112 UNUSED(config);
113 return ErrorCode::OK;
114}
115
116ErrorCode STM32VirtualUART::ReadFun(ReadPort &port)
117{
118 UNUSED(port);
119
120 return ErrorCode::EMPTY;
121}
122
123ErrorCode STM32VirtualUART::WriteFun(WritePort &port)
124{
125 auto *uart = CONTAINER_OF(&port, STM32VirtualUART, _write_port);
126
127 uart->write_sem_.Post();
128 return ErrorCode::EMPTY;
129}
130
131void STM32VirtualUART::RxLoop()
132{
133 while (true)
134 {
135 if (!cdc_acm_)
136 {
137 tx_thread_sleep(1);
138 continue;
139 }
140 ULONG actual_len = 0;
141 UINT status =
142 _ux_device_class_cdc_acm_read(cdc_acm_, rx_buff_, buffer_size_, &actual_len);
143 if (status == UX_SUCCESS && actual_len > 0)
144 {
145 read_port_->queue_data_->PushBatch(rx_buff_, actual_len);
146 read_port_->ProcessPendingReads(false);
147 }
148 }
149}
150
151void STM32VirtualUART::TxLoop()
152{
153 WriteInfoBlock info;
154 while (true)
155 {
156 if (!cdc_acm_)
157 {
158 tx_thread_sleep(1);
159 continue;
160 }
161
162 if (write_sem_.Wait() != ErrorCode::OK)
163 {
164 continue;
165 }
166
167 if (write_port_->queue_info_->Pop(info) == ErrorCode::OK)
168 {
169 if (write_port_->queue_data_->PopBatch(tx_buff_, info.data.size_) == ErrorCode::OK)
170 {
171 ULONG actual = 0;
172 UINT status =
173 _ux_device_class_cdc_acm_write(cdc_acm_, tx_buff_, info.data.size_, &actual);
174 write_port_->Finish(false,
175 (status == UX_SUCCESS && actual == info.data.size_)
176 ? ErrorCode::OK
177 : ErrorCode::FAILED,
178 info, actual);
179 }
180 else
181 {
182 ASSERT(false);
183 info.op.UpdateStatus(false, ErrorCode::FAILED);
184 }
185 }
186 }
187}
188
189void STM32VirtualUART::RxThreadEntry(ULONG arg)
190{
191 static_cast<STM32VirtualUART *>(reinterpret_cast<void *>(arg))->RxLoop();
192}
193
194void STM32VirtualUART::TxThreadEntry(ULONG arg)
195{
196 static_cast<STM32VirtualUART *>(reinterpret_cast<void *>(arg))->TxLoop();
197}
198
199} // namespace LibXR
200
201#endif
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:247
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:243