libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_usb.cpp
1#include "stm32_usb.hpp"
2
3#if defined(HAL_PCD_MODULE_ENABLED) && !defined(LIBXR_SYSTEM_ThreadX)
4
5using namespace LibXR;
6
7STM32VirtualUART *STM32VirtualUART::map[1];
8
9int8_t libxr_stm32_virtual_uart_init(void)
10{
11 STM32VirtualUART *uart = STM32VirtualUART::map[0];
12 USBD_CDC_SetTxBuffer(STM32VirtualUART::map[0]->usb_handle_,
13 uart->tx_buffer_.ActiveBuffer(), 0);
14 USBD_CDC_SetRxBuffer(STM32VirtualUART::map[0]->usb_handle_,
15 uart->rx_buffer_.ActiveBuffer());
16 return (USBD_OK);
17}
18
19int8_t libxr_stm32_virtual_uart_deinit(void) { return (USBD_OK); }
20
21int8_t libxr_stm32_virtual_uart_control(uint8_t cmd, uint8_t *pbuf, uint16_t len)
22{
23 UNUSED(cmd);
24 UNUSED(pbuf);
25 UNUSED(len);
26 return (USBD_OK);
27}
28
29int8_t libxr_stm32_virtual_uart_receive(uint8_t *pbuf, uint32_t *Len)
30{
31 STM32VirtualUART *uart = STM32VirtualUART::map[0];
32
33 uint8_t *buffer = nullptr;
34
35 if (pbuf == uart->rx_buffer_.ActiveBuffer())
36 {
37 buffer = uart->rx_buffer_.PendingBuffer();
38 }
39 else
40 {
41 buffer = uart->rx_buffer_.ActiveBuffer();
42 }
43
44 USBD_CDC_SetRxBuffer(STM32VirtualUART::map[0]->usb_handle_, buffer);
45
46 USBD_CDC_ReceivePacket(STM32VirtualUART::map[0]->usb_handle_);
47
48#if __DCACHE_PRESENT
49 SCB_InvalidateDCache_by_Addr(pbuf, *Len);
50#endif
51
52 uart->read_port_->queue_data_->PushBatch(pbuf, *Len);
54
55 return (USBD_OK);
56}
57
58int8_t libxr_stm32_virtual_uart_transmit(uint8_t *pbuf, uint32_t *Len, uint8_t epnum)
59{
60 UNUSED(epnum);
61 UNUSED(pbuf);
62 UNUSED(Len);
63
64 STM32VirtualUART *uart = STM32VirtualUART::map[0];
65
66 WriteInfoBlock &current_info = uart->write_info_active_;
67
68 if (!uart->tx_buffer_.HasPending())
69 {
70 return USBD_OK;
71 }
72
73 if (uart->write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
74 {
75 ASSERT(false);
76 return USBD_OK;
77 }
78
79 uart->tx_buffer_.Switch();
80
81#if defined(STM32F1)
82 uart->write_size_ = current_info.data.size_;
83 uart->writing_ = true;
84#endif
85
86 USBD_CDC_SetTxBuffer(uart->usb_handle_, uart->tx_buffer_.ActiveBuffer(),
87 current_info.data.size_);
88#if __DCACHE_PRESENT
89 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->tx_buffer_.ActiveBuffer()),
90 *Len);
91#endif
92
93 uart->write_port_->write_size_ = current_info.data.size_;
94
95 auto ans = USBD_CDC_TransmitPacket(uart->usb_handle_);
96
97 current_info.op.UpdateStatus(true, ans == USBD_OK ? ErrorCode::OK : ErrorCode::BUSY);
98
99 WriteInfoBlock next_info;
100
101 if (uart->write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
102 {
103 return USBD_OK;
104 }
105
106 if (uart->write_port_->queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(),
107 next_info.data.size_) != ErrorCode::OK)
108 {
109 ASSERT(false);
110 return USBD_OK;
111 }
112
113 uart->tx_buffer_.EnablePending();
114
115 return (USBD_OK);
116}
117
118#if defined(STM32F1)
119extern "C" void STM32_USB_ISR_Handler_F1(void)
120{
121 if (STM32VirtualUART::map[0] == nullptr)
122 {
123 return;
124 }
125
126 auto p_data_class = reinterpret_cast<USBD_CDC_HandleTypeDef *>(
127 STM32VirtualUART::map[0]->usb_handle_->pClassData);
128
129 if (p_data_class == nullptr)
130 {
131 return;
132 }
133
134 static uint32_t last_tx_state = 0;
135
136 if (last_tx_state != 0 && p_data_class->TxState == 0 &&
137 STM32VirtualUART::map[0]->writing_)
138 {
139 STM32VirtualUART::map[0]->writing_ = false;
140 libxr_stm32_virtual_uart_transmit(STM32VirtualUART::map[0]->tx_buffer_.ActiveBuffer(),
141 &STM32VirtualUART::map[0]->write_size_, 0);
142 }
143
144 last_tx_state = p_data_class->TxState;
145}
146#endif
147
148ErrorCode STM32VirtualUART::WriteFun(WritePort &port)
149{
150 STM32VirtualUART *uart = CONTAINER_OF(&port, STM32VirtualUART, _write_port);
151 auto p_data_class =
152 reinterpret_cast<USBD_CDC_HandleTypeDef *>(uart->usb_handle_->pClassData);
153
154 WriteInfoBlock info;
155
156 if (p_data_class == nullptr)
157 {
158 port.queue_info_->Pop(info);
159 port.queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(), info.data.size_);
160 port.Finish(false, ErrorCode::INIT_ERR, info, 0);
161 return ErrorCode::INIT_ERR;
162 }
163
164 if (uart->tx_buffer_.HasPending())
165 {
166 return ErrorCode::FULL;
167 }
168
169 if (port.queue_info_->Peek(info) != ErrorCode::OK)
170 {
171 return ErrorCode::EMPTY;
172 }
173
174 if (port.queue_data_->PopBatch(uart->tx_buffer_.PendingBuffer(), info.data.size_) !=
175 ErrorCode::OK)
176 {
177 ASSERT(false);
178 return ErrorCode::EMPTY;
179 }
180
181 uart->tx_buffer_.EnablePending();
182
183#if defined(STM32F1)
184 if (!uart->writing_ && uart->tx_buffer_.HasPending())
185#else
186 if (p_data_class->TxState == 0)
187#endif
188 {
189 uart->tx_buffer_.Switch();
190 port.queue_info_->Pop(uart->write_info_active_);
191
192#if defined(STM32F1)
193 uart->write_size_ = info.data.size_;
194 uart->writing_ = true;
195#endif
196
197 USBD_CDC_SetTxBuffer(uart->usb_handle_, uart->tx_buffer_.ActiveBuffer(),
198 info.data.size_);
199#if __DCACHE_PRESENT
200 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->tx_buffer_.ActiveBuffer()),
201 info.data.size_);
202#endif
203
204 port.write_size_ = info.data.size_;
205
206 auto ans = USBD_CDC_TransmitPacket(uart->usb_handle_);
207
208 info.op.UpdateStatus(true, ans == USBD_OK ? ErrorCode::OK : ErrorCode::BUSY);
209
210 return ErrorCode::FAILED;
211 }
212
213 return ErrorCode::FAILED;
214}
215
216ErrorCode STM32VirtualUART::ReadFun(ReadPort &port)
217{
218 UNUSED(port);
219 return ErrorCode::EMPTY;
220}
221
222STM32VirtualUART::STM32VirtualUART(USBD_HandleTypeDef &usb_handle, uint8_t *tx_buffer,
223 uint8_t *rx_buffer, uint32_t tx_queue_size)
224 : UART(&_read_port, &_write_port),
225 usb_handle_(&usb_handle),
226 tx_buffer_(RawData(tx_buffer, APP_TX_DATA_SIZE)),
227 rx_buffer_(RawData(rx_buffer, APP_RX_DATA_SIZE)),
228 _write_port(tx_queue_size, APP_TX_DATA_SIZE),
229 _read_port(APP_RX_DATA_SIZE)
230{
231 map[0] = this;
232
233 static USBD_CDC_ItfTypeDef usbd_cdc_itf = Apply<USBD_CDC_ItfTypeDef>();
234
235 USBD_CDC_RegisterInterface(usb_handle_, &usbd_cdc_itf);
236
237 _write_port = WriteFun;
238 _read_port = ReadFun;
239
240 USBD_CDC_ReceivePacket(usb_handle_);
241}
242
244{
245 UNUSED(config);
246 return ErrorCode::OK;
247}
248
249#endif
size_t size_
数据大小(字节)。 The size of the data (in bytes).
uint8_t * PendingBuffer()
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
uint8_t * ActiveBuffer()
获取当前正在使用的缓冲区指针 Returns the currently active buffer
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
原始数据封装类。 A class for encapsulating raw data.
ReadPort class for handling read operations.
Definition libxr_rw.hpp:268
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:127
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:51
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:52
WritePort class for handling write operations.
Definition libxr_rw.hpp:402
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:208
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:245
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:241
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44