Skip to content

Commit 089c1bb

Browse files
committed
Add start to STM32 USB device driver.
1 parent 52e23e5 commit 089c1bb

File tree

6 files changed

+498
-2
lines changed

6 files changed

+498
-2
lines changed

libraries/USBDevice/USBDevice/USBEndpoints.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ typedef enum {
4343
#include "USBEndpoints_LPC11U.h"
4444
#elif defined(TARGET_KL25Z)
4545
#include "USBEndpoints_KL25Z.h"
46+
#elif defined (TARGET_STM32F4XX)
47+
#include "USBEndpoints_STM32F4.h"
4648
#else
4749
#error "Unknown target type"
4850
#endif
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* Copyright (c) 2010-2011 mbed.org, MIT License
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4+
* and associated documentation files (the "Software"), to deal in the Software without
5+
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
6+
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
7+
* Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or
10+
* substantial portions of the Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13+
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17+
*/
18+
19+
#define NUMBER_OF_LOGICAL_ENDPOINTS (4)
20+
#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
21+
22+
/* Define physical endpoint numbers */
23+
24+
/* Endpoint No. Type(s) MaxPacket DoubleBuffer */
25+
/* ---------------- ------------ ---------- --- */
26+
#define EP0OUT (0) /* Control 64 No */
27+
#define EP0IN (1) /* Control 64 No */
28+
#define EP1OUT (2) /* Int/Bulk/Iso 64/64/1023 Yes */
29+
#define EP1IN (3) /* Int/Bulk/Iso 64/64/1023 Yes */
30+
#define EP2OUT (4) /* Int/Bulk/Iso 64/64/1023 Yes */
31+
#define EP2IN (5) /* Int/Bulk/Iso 64/64/1023 Yes */
32+
#define EP3OUT (6) /* Int/Bulk/Iso 64/64/1023 Yes */
33+
#define EP3IN (7) /* Int/Bulk/Iso 64/64/1023 Yes */
34+
35+
/* Maximum Packet sizes */
36+
37+
#define MAX_PACKET_SIZE_EP0 (64)
38+
#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
39+
#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
40+
#define MAX_PACKET_SIZE_EP3 (64) /* Int/Bulk */
41+
42+
#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
43+
#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
44+
#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
45+
46+
/* Generic endpoints - intended to be portable accross devices */
47+
/* and be suitable for simple USB devices. */
48+
49+
/* Bulk endpoint */
50+
#define EPBULK_OUT (EP2OUT)
51+
#define EPBULK_IN (EP2IN)
52+
/* Interrupt endpoint */
53+
#define EPINT_OUT (EP1OUT)
54+
#define EPINT_IN (EP1IN)
55+
/* Isochronous endpoint */
56+
#define EPISO_OUT (EP3OUT)
57+
#define EPISO_IN (EP3IN)
58+
59+
#define MAX_PACKET_SIZE_EPBULK (MAX_PACKET_SIZE_EP2)
60+
#define MAX_PACKET_SIZE_EPINT (MAX_PACKET_SIZE_EP1)
61+
#define MAX_PACKET_SIZE_EPISO (MAX_PACKET_SIZE_EP3_ISO)

libraries/USBDevice/USBDevice/USBHAL.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ class USBHAL {
7474
virtual bool EP2_IN_callback(){return false;};
7575
virtual bool EP3_OUT_callback(){return false;};
7676
virtual bool EP3_IN_callback(){return false;};
77+
#if !defined(TARGET_STM32F4)
7778
virtual bool EP4_OUT_callback(){return false;};
7879
virtual bool EP4_IN_callback(){return false;};
79-
8080
#if !defined(TARGET_LPC11U24)
8181
virtual bool EP5_OUT_callback(){return false;};
8282
virtual bool EP5_IN_callback(){return false;};
@@ -101,6 +101,7 @@ class USBHAL {
101101
virtual bool EP15_OUT_callback(){return false;};
102102
virtual bool EP15_IN_callback(){return false;};
103103
#endif
104+
#endif
104105

105106
private:
106107
void usbisr(void);
@@ -109,6 +110,8 @@ class USBHAL {
109110

110111
#if defined(TARGET_LPC11U24)
111112
bool (USBHAL::*epCallback[10 - 2])(void);
113+
#elif defined(TARGET_STM32F4XX)
114+
bool (USBHAL::*epCallback[8 - 2])(void);
112115
#else
113116
bool (USBHAL::*epCallback[32 - 2])(void);
114117
#endif

libraries/USBDevice/USBDevice/USBHAL_LPC11U.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ void USBHAL::EP0readStage(void) {
256256
void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
257257
// Start and endpoint 0 write
258258

259-
// The USB ISR will call USBDevice_EP0in() when the data has
259+
// The USB SR will call USBDevice_EP0in() when the data has
260260
// been written, the USBDevice layer then calls
261261
// USBBusInterface_EP0getWriteResult() to complete the transaction.
262262

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/* Copyright (c) 2010-2011 mbed.org, MIT License
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4+
* and associated documentation files (the "Software"), to deal in the Software without
5+
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
6+
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
7+
* Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or
10+
* substantial portions of the Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13+
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17+
*/
18+
19+
#if defined(TARGET_STM32F4XX)
20+
21+
#include "USBHAL.h"
22+
#include "USBRegs_STM32.h"
23+
#include "pinmap.h"
24+
25+
USBHAL * USBHAL::instance;
26+
27+
static volatile int epComplete = 0;
28+
29+
static uint32_t bufferEnd = 0;
30+
static const uint32_t rxFifoSize = 512;
31+
static uint32_t rxFifoCount = 0;
32+
33+
static uint32_t setupBuffer[MAX_PACKET_SIZE_EP0 >> 2];
34+
35+
uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
36+
return 0;
37+
}
38+
39+
USBHAL::USBHAL(void) {
40+
NVIC_DisableIRQ(OTG_FS_IRQn);
41+
epCallback[0] = &USBHAL::EP1_OUT_callback;
42+
epCallback[1] = &USBHAL::EP1_IN_callback;
43+
epCallback[2] = &USBHAL::EP2_OUT_callback;
44+
epCallback[3] = &USBHAL::EP2_IN_callback;
45+
epCallback[4] = &USBHAL::EP3_OUT_callback;
46+
epCallback[5] = &USBHAL::EP3_IN_callback;
47+
48+
// Enable power and clocking
49+
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
50+
51+
pin_function(PA_8, STM_PIN_DATA(2, 10));
52+
pin_function(PA_9, STM_PIN_DATA(0, 0));
53+
pin_function(PA_10, STM_PIN_DATA(2, 10));
54+
pin_function(PA_11, STM_PIN_DATA(2, 10));
55+
pin_function(PA_12, STM_PIN_DATA(2, 10));
56+
57+
// Set ID pin to open drain with pull-up resistor
58+
pin_mode(PA_10, OpenDrain);
59+
GPIOA->PUPDR &= ~(0x3 << 20);
60+
GPIOA->PUPDR |= 1 << 20;
61+
62+
// Set VBUS pin to open drain
63+
pin_mode(PA_9, OpenDrain);
64+
65+
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
66+
67+
OTG_FS->GREGS.GAHBCFG |= (1 << 0); // Set GINTMSK
68+
OTG_FS->GREGS.GINTSTS |= (1 << 4); // RXFLVL
69+
70+
OTG_FS->GREGS.GUSBCFG |= (0xF << 10); // TRDT to 0xF for 72MHz AHB2
71+
OTG_FS->GREGS.GINTMSK |= (1 << 1) | // Mode mismatch
72+
(1 << 2) | // OTG
73+
(1 << 3) | // SOF
74+
(1 << 4) | // RX FIFO not empty
75+
(1 << 10) | // Early suspend
76+
(1 << 11) | // USB suspend
77+
(1 << 12) | // USB reset
78+
(1 << 13); // Enumeration Done
79+
80+
OTG_FS->DREGS.DCFG |= (0x3 << 0) | // Full speed
81+
(1 << 2); // Non-zero-length status OUT handshake
82+
83+
OTG_FS->GREGS.GCCFG |= (1 << 19) | // VBUS sensing
84+
(1 << 16); // Power Up
85+
86+
instance = this;
87+
NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisr);
88+
NVIC_SetPriority(OTG_FS_IRQn, 1);
89+
}
90+
91+
USBHAL::~USBHAL(void) {
92+
}
93+
94+
void USBHAL::connect(void) {
95+
NVIC_EnableIRQ(OTG_FS_IRQn);
96+
}
97+
98+
void USBHAL::disconnect(void) {
99+
NVIC_DisableIRQ(OTG_FS_IRQn);
100+
}
101+
102+
void USBHAL::configureDevice(void) {
103+
}
104+
105+
void USBHAL::unconfigureDevice(void) {
106+
}
107+
108+
void USBHAL::setAddress(uint8_t address) {
109+
OTG_FS->DREGS.DCFG |= (address << 4);
110+
EP0write(0, 0);
111+
}
112+
113+
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
114+
if (endpoint & 0x1) { // In Endpoint
115+
}
116+
else {
117+
}
118+
return true;
119+
}
120+
121+
// read setup packet
122+
void USBHAL::EP0setup(uint8_t *buffer) {
123+
memcpy(buffer, setupBuffer, MAX_PACKET_SIZE_EP0);
124+
}
125+
126+
void USBHAL::EP0readStage(void) {
127+
}
128+
129+
void USBHAL::EP0read(void) {
130+
}
131+
132+
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
133+
uint32_t* buffer32 = (uint32_t *) buffer;
134+
uint32_t length = rxFifoCount;
135+
for (uint32_t i = 0; i < length; i += 4) {
136+
buffer32[i >> 2] = OTG_FS->FIFO[0][0];
137+
}
138+
139+
rxFifoCount = 0;
140+
return length;
141+
}
142+
143+
void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
144+
OTG_FS->INEP_REGS[0].DIEPTSIZ = (1 << 19) | // 1 packet
145+
(size << 0); // Size of packet
146+
OTG_FS->INEP_REGS[0].DIEPCTL |= (1 << 31) | // Enable endpoint
147+
(1 << 26); // CNAK
148+
149+
while ((OTG_FS->INEP_REGS[0].DTXFSTS & 0XFFFF) < ((size + 3) >> 2));
150+
151+
for (uint32_t i=0; i<(size + 3) >> 2; i++, buffer+=4) {
152+
OTG_FS->FIFO[0][0] = *(uint32_t *)buffer;
153+
}
154+
}
155+
156+
void USBHAL::EP0getWriteResult(void) {
157+
}
158+
159+
void USBHAL::EP0stall(void) {
160+
stallEndpoint(EP0IN);
161+
// stallEndpoint(EP0OUT);
162+
}
163+
164+
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
165+
return EP_PENDING;
166+
}
167+
168+
EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
169+
return EP_COMPLETED;
170+
}
171+
172+
EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
173+
return EP_COMPLETED;
174+
}
175+
176+
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
177+
return EP_COMPLETED;
178+
}
179+
180+
void USBHAL::stallEndpoint(uint8_t endpoint) {
181+
if (endpoint & 0x1) { // In EP
182+
OTG_FS->INEP_REGS[endpoint >> 1].DIEPCTL |= (1 << 30) | // Disable
183+
(1 << 21); // Stall
184+
}
185+
else { // Out EP
186+
OTG_FS->DREGS.DCTL |= (1 << 9); // Set global out NAK
187+
OTG_FS->OUTEP_REGS[endpoint >> 1].DOEPCTL |= (1 << 30) | // Disable
188+
(1 << 21); // Stall
189+
}
190+
}
191+
192+
void USBHAL::unstallEndpoint(uint8_t endpoint) {
193+
194+
}
195+
196+
bool USBHAL::getEndpointStallState(uint8_t endpoint) {
197+
return false;
198+
}
199+
200+
void USBHAL::remoteWakeup(void) {
201+
}
202+
203+
204+
void USBHAL::_usbisr(void) {
205+
instance->usbisr();
206+
}
207+
208+
209+
void USBHAL::usbisr(void) {
210+
if (OTG_FS->GREGS.GINTSTS & (1 << 12)) { // USB Reset
211+
// Set SNAK bits
212+
OTG_FS->OUTEP_REGS[0].DOEPCTL |= (1 << 27);
213+
OTG_FS->OUTEP_REGS[1].DOEPCTL |= (1 << 27);
214+
OTG_FS->OUTEP_REGS[2].DOEPCTL |= (1 << 27);
215+
OTG_FS->OUTEP_REGS[3].DOEPCTL |= (1 << 27);
216+
217+
OTG_FS->DREGS.DAINTMSK = (1 << 0) | // In 0 EP Mask
218+
(1 << 16); // Out 0 EP Mask
219+
OTG_FS->DREGS.DOEPMSK = (1 << 0) | // Transfer complete
220+
(1 << 3); // Setup phase done
221+
222+
OTG_FS->DREGS.DIEPEMPMSK = (1 << 0);
223+
224+
bufferEnd = 0;
225+
226+
OTG_FS->GREGS.GRXFSIZ = rxFifoSize >> 2;
227+
bufferEnd += rxFifoSize >> 2;
228+
229+
OTG_FS->GREGS.DIEPTXF0_HNPTXFSIZ = ((MAX_PACKET_SIZE_EP0 >> 2) << 16) |
230+
bufferEnd << 0;
231+
bufferEnd += (MAX_PACKET_SIZE_EP0 >> 2);
232+
OTG_FS->OUTEP_REGS[0].DOEPTSIZ |= (0x3 << 29); // 3 setup packets
233+
234+
OTG_FS->GREGS.GINTSTS |= (1 << 12);
235+
}
236+
237+
if (OTG_FS->GREGS.GINTSTS & (1 << 13)) { // Enumeration done
238+
OTG_FS->INEP_REGS[0].DIEPCTL &= ~(0x3 << 0); // 64 byte packet size
239+
OTG_FS->GREGS.GINTSTS |= (1 << 13);
240+
}
241+
242+
if (OTG_FS->GREGS.GINTSTS & (1 << 4)) { // RX FIFO not empty
243+
uint32_t status = OTG_FS->GREGS.GRXSTSP;
244+
245+
uint32_t endpoint = status & 0xF;
246+
uint32_t length = (status >> 4) & 0x7FF;
247+
uint32_t type = (status >> 17) & 0xF;
248+
249+
rxFifoCount = length;
250+
251+
if (type == 0x6) {
252+
// Setup packet
253+
for (uint32_t i=0; i<length; i+=4) {
254+
setupBuffer[i >> 2] = OTG_FS->FIFO[0][i >> 2];
255+
}
256+
rxFifoCount = 0;
257+
}
258+
259+
if (type == 0x4) {
260+
// Setup complete
261+
EP0setupCallback();
262+
OTG_FS->OUTEP_REGS[0].DOEPCTL |= (1 << 31) |
263+
(1 << 26); // CNAK
264+
}
265+
266+
for (uint32_t i=0; i<rxFifoCount; i+=4) {
267+
(void) OTG_FS->FIFO[0][0];
268+
}
269+
}
270+
271+
if (OTG_FS->GREGS.GINTSTS & (1 << 18)) { // In endpoint interrupt
272+
if (OTG_FS->DREGS.DAINT & (1 << 0)) { // In EP 0
273+
if (OTG_FS->INEP_REGS[0].DIEPINT & (1 << 7)) {
274+
EP0in();
275+
}
276+
}
277+
}
278+
}
279+
280+
281+
#endif

0 commit comments

Comments
 (0)