Skip to content

Commit 1ad15e4

Browse files
committed
More changes to bring STM32 USB HAL to a pretty much working state.
1 parent 089c1bb commit 1ad15e4

File tree

1 file changed

+159
-23
lines changed

1 file changed

+159
-23
lines changed

libraries/USBDevice/USBDevice/USBHAL_STM32F4.cpp

Lines changed: 159 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,59 @@ void USBHAL::setAddress(uint8_t address) {
110110
EP0write(0, 0);
111111
}
112112

113-
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
113+
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket,
114+
uint32_t flags) {
115+
uint32_t epIndex = endpoint >> 1;
116+
117+
uint32_t type;
118+
switch (endpoint) {
119+
case EP0IN:
120+
case EP0OUT:
121+
type = 0;
122+
break;
123+
case EPISO_IN:
124+
case EPISO_OUT:
125+
type = 1;
126+
case EPBULK_IN:
127+
case EPBULK_OUT:
128+
type = 2;
129+
break;
130+
case EPINT_IN:
131+
case EPINT_OUT:
132+
type = 3;
133+
break;
134+
}
135+
136+
// Generic in or out EP controls
137+
uint32_t control = (maxPacket << 0) | // Packet size
138+
(1 << 15) | // Active endpoint
139+
(type << 18); // Endpoint type
140+
114141
if (endpoint & 0x1) { // In Endpoint
142+
// Set up the Tx FIFO
143+
OTG_FS->GREGS.DIEPTXF[epIndex - 1] = ((maxPacket >> 2) << 16) |
144+
(bufferEnd << 0);
145+
bufferEnd += maxPacket >> 2;
146+
147+
// Set the In EP specific control settings
148+
if (endpoint != EP0IN) {
149+
control |= (1 << 28); // SD0PID
150+
}
151+
152+
control |= (epIndex << 22) | // TxFIFO index
153+
(1 << 27); // SNAK
154+
OTG_FS->INEP_REGS[epIndex].DIEPCTL = control;
155+
156+
// Unmask the interrupt
157+
OTG_FS->DREGS.DAINTMSK |= (1 << epIndex);
115158
}
116-
else {
159+
else { // Out endpoint
160+
// Set the out EP specific control settings
161+
control |= (1 << 26); // CNAK
162+
OTG_FS->OUTEP_REGS[epIndex].DOEPCTL = control;
163+
164+
// Unmask the interrupt
165+
OTG_FS->DREGS.DAINTMSK |= (1 << (epIndex + 16));
117166
}
118167
return true;
119168
}
@@ -141,16 +190,7 @@ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
141190
}
142191

143192
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-
}
193+
endpointWrite(0, buffer, size);
154194
}
155195

156196
void USBHAL::EP0getWriteResult(void) {
@@ -162,19 +202,58 @@ void USBHAL::EP0stall(void) {
162202
}
163203

164204
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
205+
uint32_t epIndex = endpoint >> 1;
206+
OTG_FS->OUTEP_REGS[epIndex].DOEPTSIZ = (1 << 29) | // 1 packet per frame
207+
(1 << 19) | // 1 packet
208+
(maximumSize << 0); // Packet size
209+
OTG_FS->OUTEP_REGS[epIndex].DOEPCTL |= (1 << 31) | // Enable endpoint
210+
(1 << 26); // Clear NAK
211+
212+
epComplete &= ~(1 << endpoint);
165213
return EP_PENDING;
166214
}
167215

168216
EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
217+
if (!(epComplete & (1 << endpoint))) {
218+
return EP_PENDING;
219+
}
220+
221+
uint32_t* buffer32 = (uint32_t *) buffer;
222+
uint32_t length = rxFifoCount;
223+
for (uint32_t i = 0; i < length; i += 4) {
224+
buffer32[i >> 2] = OTG_FS->FIFO[endpoint >> 1][0];
225+
}
226+
rxFifoCount = 0;
227+
*bytesRead = length;
169228
return EP_COMPLETED;
170229
}
171230

172231
EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
173-
return EP_COMPLETED;
232+
uint32_t epIndex = endpoint >> 1;
233+
OTG_FS->INEP_REGS[epIndex].DIEPTSIZ = (1 << 19) | // 1 packet
234+
(size << 0); // Size of packet
235+
OTG_FS->INEP_REGS[epIndex].DIEPCTL |= (1 << 31) | // Enable endpoint
236+
(1 << 26); // CNAK
237+
OTG_FS->DREGS.DIEPEMPMSK = (1 << epIndex);
238+
239+
while ((OTG_FS->INEP_REGS[epIndex].DTXFSTS & 0XFFFF) < ((size + 3) >> 2));
240+
241+
for (uint32_t i=0; i<(size + 3) >> 2; i++, data+=4) {
242+
OTG_FS->FIFO[epIndex][0] = *(uint32_t *)data;
243+
}
244+
245+
epComplete &= ~(1 << endpoint);
246+
247+
return EP_PENDING;
174248
}
175249

176250
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
177-
return EP_COMPLETED;
251+
if (epComplete & (1 << endpoint)) {
252+
epComplete &= ~(1 << endpoint);
253+
return EP_COMPLETED;
254+
}
255+
256+
return EP_PENDING;
178257
}
179258

180259
void USBHAL::stallEndpoint(uint8_t endpoint) {
@@ -218,8 +297,7 @@ void USBHAL::usbisr(void) {
218297
(1 << 16); // Out 0 EP Mask
219298
OTG_FS->DREGS.DOEPMSK = (1 << 0) | // Transfer complete
220299
(1 << 3); // Setup phase done
221-
222-
OTG_FS->DREGS.DIEPEMPMSK = (1 << 0);
300+
OTG_FS->DREGS.DIEPMSK |= (1 << 0);
223301

224302
bufferEnd = 0;
225303

@@ -231,18 +309,18 @@ void USBHAL::usbisr(void) {
231309
bufferEnd += (MAX_PACKET_SIZE_EP0 >> 2);
232310
OTG_FS->OUTEP_REGS[0].DOEPTSIZ |= (0x3 << 29); // 3 setup packets
233311

234-
OTG_FS->GREGS.GINTSTS |= (1 << 12);
312+
OTG_FS->GREGS.GINTSTS = (1 << 12);
235313
}
236314

237315
if (OTG_FS->GREGS.GINTSTS & (1 << 13)) { // Enumeration done
238316
OTG_FS->INEP_REGS[0].DIEPCTL &= ~(0x3 << 0); // 64 byte packet size
239-
OTG_FS->GREGS.GINTSTS |= (1 << 13);
317+
OTG_FS->GREGS.GINTSTS = (1 << 13);
240318
}
241319

242320
if (OTG_FS->GREGS.GINTSTS & (1 << 4)) { // RX FIFO not empty
243321
uint32_t status = OTG_FS->GREGS.GRXSTSP;
244322

245-
uint32_t endpoint = status & 0xF;
323+
uint32_t endpoint = (status & 0xF) << 1;
246324
uint32_t length = (status >> 4) & 0x7FF;
247325
uint32_t type = (status >> 17) & 0xF;
248326

@@ -263,18 +341,76 @@ void USBHAL::usbisr(void) {
263341
(1 << 26); // CNAK
264342
}
265343

344+
if (type == 0x2) {
345+
// Out packet
346+
if (endpoint == 0) {
347+
EP0out();
348+
}
349+
else {
350+
epComplete |= (1 << endpoint);
351+
if ((instance->*(epCallback[endpoint - 2]))()) {
352+
epComplete &= (1 << endpoint);
353+
}
354+
}
355+
}
356+
266357
for (uint32_t i=0; i<rxFifoCount; i+=4) {
267358
(void) OTG_FS->FIFO[0][0];
268-
}
359+
}
360+
OTG_FS->GREGS.GINTSTS = (1 << 4);
269361
}
270362

271363
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();
364+
// Loop through the in endpoints
365+
for (uint32_t i=0; i<4; i++) {
366+
if (OTG_FS->DREGS.DAINT & (1 << i)) { // Interrupt is on endpoint
367+
368+
// If the Tx FIFO is empty on EP0 we need to send a further
369+
// packet, so call EP0in()
370+
if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 7)) {// Tx FIFO empty
371+
// If the Tx FIFO is empty on EP0 we need to send a further
372+
// packet, so call EP0in()
373+
if (i == 0) {
374+
EP0in();
375+
}
376+
// Clear the interrupt
377+
OTG_FS->INEP_REGS[i].DIEPINT = (1 << 7);
378+
// Stop firing Tx empty interrupts
379+
// Will get turned on again if another write is called
380+
OTG_FS->DREGS.DIEPEMPMSK &= ~(1 << i);
381+
}
382+
383+
// If the transfer is complete
384+
if (OTG_FS->INEP_REGS[i].DIEPINT & (1 << 0)) { // Tx Complete
385+
epComplete |= (1 << (1 + (i << 1)));
386+
OTG_FS->INEP_REGS[i].DIEPINT = (1 << 0);
387+
}
275388
}
276389
}
390+
OTG_FS->GREGS.GINTSTS = (1 << 18);
277391
}
392+
393+
if (OTG_FS->GREGS.GINTSTS & (1 << 3)) { // Start of frame
394+
SOF((OTG_FS->GREGS.GRXSTSR >> 17) & 0xF);
395+
OTG_FS->GREGS.GINTSTS = (1 << 3);
396+
}
397+
398+
if (OTG_FS->GREGS.GINTSTS & (1 << 1)) {
399+
OTG_FS->GREGS.GINTSTS = (1 << 1);
400+
}
401+
402+
if (OTG_FS->GREGS.GINTSTS & (1 << 2)) {
403+
OTG_FS->GREGS.GINTSTS = (1 << 2);
404+
}
405+
406+
if (OTG_FS->GREGS.GINTSTS & (1 << 10)) {
407+
OTG_FS->GREGS.GINTSTS = (1 << 10);
408+
}
409+
410+
if (OTG_FS->GREGS.GINTSTS & (1 << 11)) {
411+
OTG_FS->GREGS.GINTSTS = (1 << 11);
412+
}
413+
278414
}
279415

280416

0 commit comments

Comments
 (0)