1
0
mirror of https://github.com/gdsports/USBHost_t36 synced 2024-08-13 16:53:54 -04:00

Add reset-enumeration mutual exclusion

This commit is contained in:
PaulStoffregen 2017-03-03 04:58:10 -08:00
parent 2e1e9748e0
commit 86c1bbe6ee
5 changed files with 44 additions and 20 deletions

View File

@ -161,6 +161,7 @@ protected:
static void disconnect_Device(Device_t *dev);
static void enumeration(const Transfer_t *transfer);
static void driver_ready_for_device(USBDriver *driver);
static volatile bool enumeration_busy;
private:
static void isr();
static void claim_drivers(Device_t *dev);
@ -326,7 +327,6 @@ protected:
virtual void timer_event(USBDriverTimer *whichTimer);
virtual void disconnect();
bool can_send_control_now();
void send_poweron(uint32_t port);
void send_getstatus(uint32_t port);
void send_clearstatus_connect(uint32_t port);
@ -335,15 +335,14 @@ protected:
void send_clearstatus_overcurrent(uint32_t port);
void send_clearstatus_reset(uint32_t port);
void send_setreset(uint32_t port);
static void callback(const Transfer_t *transfer);
void status_change(const Transfer_t *transfer);
void new_port_status(uint32_t port, uint32_t status);
void start_debounce_timer(uint32_t port);
void stop_debounce_timer(uint32_t port);
static volatile bool reset_busy;
USBDriverTimer debouncetimer;
//USBDriverTimer mytimer;
USBDriverTimer resettimer;
setup_t setup;
Pipe_t *changepipe;

View File

@ -175,7 +175,6 @@ void USBHost::begin()
NVIC_ENABLE_IRQ(IRQ_USBHS);
USBHS_USBINTR = USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0 | USBHS_USBINTR_TIE1;
USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE;
USBHS_USBINTR |= USBHS_USBINTR_AAE;
USBHS_USBINTR |= USBHS_USBINTR_UPIE | USBHS_USBINTR_UAIE;
}
@ -313,12 +312,16 @@ void USBHost::isr()
//println("timer0");
if (port_state == PORT_STATE_DEBOUNCE) {
port_state = PORT_STATE_RESET;
// Since we have only 1 port, no other device can
// be in reset or enumeration. If multiple ports
// are ever supported, we would need to remain in
// debounce if any other port was resetting or
// enumerating a device.
USBHS_PORTSC1 |= USBHS_PORTSC_PR; // begin reset sequence
println(" begin reset");
} else if (port_state == PORT_STATE_RECOVERY) {
port_state = PORT_STATE_ACTIVE;
println(" end recovery");
// HCSPARAMS TTCTRL page 1671
uint32_t speed = (USBHS_PORTSC1 >> 26) & 3;
rootdev = new_Device(speed, 0, 0);

View File

@ -31,6 +31,10 @@ static setup_t enumsetup __attribute__ ((aligned(16)));
static uint16_t enumlen;
static Device_t *devlist=NULL;
// True while any device is present but not yet fully configured.
// Only one USB device may be in this state at a time (responding
// to address zero) and using the enumeration static buffer.
volatile bool USBHost::enumeration_busy = false;
static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen);
static void pipe_set_addr(Pipe_t *pipe, uint32_t addr);
@ -79,9 +83,9 @@ Device_t * USBHost::new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_p
}
dev->control_pipe->callback_function = &enumeration;
dev->control_pipe->direction = 1; // 1=IN
// TODO: exclusive access to enumeration process
// any new devices detected while enumerating would
// go onto a waiting list
// Here is where the enumeration process officially begins.
// Only a single device can enumerate at a time.
USBHost::enumeration_busy = true;
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR
queue_Control_Transfer(dev, &enumsetup, enumbuf, NULL);
if (devlist == NULL) {
@ -227,8 +231,11 @@ void USBHost::enumeration(const Transfer_t *transfer)
case 14: // device is now configured
claim_drivers(dev);
dev->enum_state = 15;
// TODO: unlock exclusive access to enumeration process
// if any detected devices are waiting, start the first
// unlock exclusive access to enumeration process. If any
// more devices are waiting, the hub driver is responsible
// for resetting their ports and starting their enumeration
// when the port enables.
USBHost::enumeration_busy = false;
return;
case 15: // control transfers for other stuff?
// TODO: handle other standard control: set/clear feature, etc

33
hub.cpp
View File

@ -24,7 +24,12 @@
#include <Arduino.h>
#include "USBHost.h"
USBHub::USBHub() : debouncetimer(this), /* mytimer(this), */ resettimer(this)
// True when any hub port is in the reset or reset recovery phase.
// Only one USB device may be reset at a time, because it will
// begin responding to address zero.
volatile bool USBHub::reset_busy = false;
USBHub::USBHub() : debouncetimer(this), resettimer(this)
{
// TODO: free Device_t, Pipe_t & Transfer_t we will need
driver_ready_for_device(this);
@ -38,12 +43,7 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t
println("USBHub memory usage = ", sizeof(USBHub));
println("USBHub claim_device this=", (uint32_t)this, HEX);
// timer testing TODO: remove this later
//mytimer.init(this);
//mytimer.pointer = (void *)"This is mytimer";
//mytimer.start(99129);
resettimer.pointer = (void *)"Hello, I'm resettimer";
//resettimer.start(12345);
debouncetimer.pointer = (void *)"Debounce Timer";
// check for HUB type
@ -347,9 +347,13 @@ void USBHub::new_port_status(uint32_t port, uint32_t status)
case PORT_DEBOUNCE5:
if (status & 0x0001) {
if (++state > PORT_DEBOUNCE5) {
// TODO: check for exclusive access to
// enumeration process... stay in debounce
// and add to wait list if enumeration busy
if (USBHub::reset_busy || USBHost::enumeration_busy) {
// wait in debounce state if another port is
// resetting or a device is busy enumerating
state = PORT_DEBOUNCE5;
break;
}
USBHub::reset_busy = true;
stop_debounce_timer(port);
state = PORT_RESET;
println("sending reset");
@ -409,10 +413,21 @@ void USBHub::timer_event(USBDriverTimer *timer)
// begin enumeration process
uint8_t speed = port_doing_reset_speed;
devicelist[port-1] = new_Device(speed, device->address, port);
// TODO: if return is NULL, what to do? Panic?
// Can we disable the port? Will this device
// play havoc if it sits unconfigured responding
// to address zero? Does that even matter? Maybe
// we have far worse issues when memory isn't
// available?!
USBHub::reset_busy = false;
state = PORT_ACTIVE;
}
}
}
// TODO: testing only!!!
static uint32_t count=0;
if (++count > 36) while (1) ; // stop here
}
void USBHub::start_debounce_timer(uint32_t port)

View File

@ -27,7 +27,7 @@
// Memory allocation
static Device_t memory_Device[3];
static Device_t memory_Device[4];
static Pipe_t memory_Pipe[8] __attribute__ ((aligned(32)));
static Transfer_t memory_Transfer[34] __attribute__ ((aligned(32)));