mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-24 10:02:15 -05:00
Add reset-enumeration mutual exclusion
This commit is contained in:
parent
2e1e9748e0
commit
86c1bbe6ee
@ -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;
|
||||
|
7
ehci.cpp
7
ehci.cpp
@ -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);
|
||||
|
@ -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
33
hub.cpp
@ -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)
|
||||
|
@ -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)));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user