Browse Source

Add lots of debugging stuff, still not transmitting anything :(

main
PaulStoffregen 7 years ago
parent
commit
3fa09c381e
2 changed files with 109 additions and 33 deletions
  1. +13
    -12
      host.h
  2. +96
    -21
      k66_usbhost.ino

+ 13
- 12
host.h View File

struct Pipe_struct { struct Pipe_struct {
// Queue Head (QH), EHCI page 46-50 // Queue Head (QH), EHCI page 46-50
struct { // must be aligned to 32 byte boundary struct { // must be aligned to 32 byte boundary
uint32_t horizontal_link;
uint32_t capabilities[2];
uint32_t current;
uint32_t next;
uint32_t alt_next;
uint32_t token;
uint32_t buffer[5];
volatile uint32_t horizontal_link;
volatile uint32_t capabilities[2];
volatile uint32_t current;
volatile uint32_t next;
volatile uint32_t alt_next;
volatile uint32_t token;
volatile uint32_t buffer[5];
} qh; } qh;
Device_t *device; Device_t *device;
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
uint8_t direction; // 0=out, 1=in uint8_t direction; // 0=out, 1=in
uint8_t active;
//uint8_t endpoint; // 0 to 15 //uint8_t endpoint; // 0 to 15
//uint8_t data01; // next packet DATA0 or DATA1 //uint8_t data01; // next packet DATA0 or DATA1
uint8_t unusedbyte[2];
uint8_t unusedbyte[1];
uint32_t unused[2]; uint32_t unused[2];
}; };


struct Transfer_struct { struct Transfer_struct {
// Queue Element Transfer Descriptor (qTD), EHCI pg 40-45 // Queue Element Transfer Descriptor (qTD), EHCI pg 40-45
struct { // must be aligned to 32 byte boundary struct { // must be aligned to 32 byte boundary
uint32_t next;
uint32_t alt_next;
uint32_t token;
uint32_t buffer[5];
volatile uint32_t next;
volatile uint32_t alt_next;
volatile uint32_t token;
volatile uint32_t buffer[5];
} qtd; } qtd;
Pipe_t *pipe; Pipe_t *pipe;
void *callback; void *callback;

+ 96
- 21
k66_usbhost.ino View File

Serial.println(sizeof(Transfer_t)); Serial.println(sizeof(Transfer_t));


MPU_RGDAAC0 |= 0x30000000; MPU_RGDAAC0 |= 0x30000000;
Serial.print("MPU_RGDAAC0 = ");
Serial.println(MPU_RGDAAC0, HEX);
MCG_C1 |= MCG_C1_IRCLKEN; // enable MCGIRCLK 32kHz MCG_C1 |= MCG_C1_IRCLKEN; // enable MCGIRCLK 32kHz
OSC0_CR |= OSC_ERCLKEN; OSC0_CR |= OSC_ERCLKEN;
SIM_SOPT2 |= SIM_SOPT2_USBREGEN; // turn on USB regulator SIM_SOPT2 |= SIM_SOPT2_USBREGEN; // turn on USB regulator
while ((USBPHY_PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK) == 0) { while ((USBPHY_PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK) == 0) {
count++; count++;
} }
print("PLL locked, waited ", count);
Serial.print("PLL locked, waited ");
Serial.println(count);
// turn on power to PHY // turn on power to PHY
USBPHY_PWD = 0; USBPHY_PWD = 0;
delay(10); delay(10);
} }
port_state = PORT_STATE_DISCONNECTED; port_state = PORT_STATE_DISCONNECTED;


USBHS_USB_SBUSCFG = 1; // System Bus Interface Configuration

// turn on the USBHS controller // turn on the USBHS controller
USBHS_USBMODE = USBHS_USBMODE_TXHSD(5) | USBHS_USBMODE_CM(3); // host mode
//USBHS_USBMODE = USBHS_USBMODE_TXHSD(5) | USBHS_USBMODE_CM(3); // host mode
USBHS_USBMODE = USBHS_USBMODE_CM(3); // host mode
USBHS_USBINTR = 0; USBHS_USBINTR = 0;
USBHS_PERIODICLISTBASE = (uint32_t)periodictable; USBHS_PERIODICLISTBASE = (uint32_t)periodictable;
USBHS_FRINDEX = 0; USBHS_FRINDEX = 0;
USBHS_ASYNCLISTADDR = 0; USBHS_ASYNCLISTADDR = 0;
USBHS_USBCMD = USBHS_USBCMD_ITC(0) | USBHS_USBCMD_RS | USBHS_USBCMD_ASP(3) |
USBHS_USBCMD = USBHS_USBCMD_ITC(8) | USBHS_USBCMD_RS |
USBHS_USBCMD_ASP(3) | USBHS_USBCMD_ASPE |
USBHS_USBCMD_FS2 | USBHS_USBCMD_FS(1); // periodic table is 32 pointers USBHS_USBCMD_FS2 | USBHS_USBCMD_FS(1); // periodic table is 32 pointers


//USBHS_PORTSC1 = USBHS_PORTSC_PP; //USBHS_PORTSC1 = USBHS_PORTSC_PP;


NVIC_ENABLE_IRQ(IRQ_USBHS); NVIC_ENABLE_IRQ(IRQ_USBHS);
USBHS_USBINTR = USBHS_USBINTR_UE | USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0; USBHS_USBINTR = USBHS_USBINTR_UE | USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0;
USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE;
USBHS_USBINTR |= USBHS_USBINTR_AAE;


delay(25); delay(25);
Serial.println("Plug in device..."); Serial.println("Plug in device...");
digitalWrite(32, HIGH); // connect device digitalWrite(32, HIGH); // connect device


delay(5000);
Serial.println();
Serial.println("Ring Doorbell");
USBHS_USBCMD |= USBHS_USBCMD_IAA;
} }


void loop() void loop()
uint32_t stat = USBHS_USBSTS; uint32_t stat = USBHS_USBSTS;
USBHS_USBSTS = stat; // clear pending interrupts USBHS_USBSTS = stat; // clear pending interrupts
//stat &= USBHS_USBINTR; // mask away unwanted interrupts //stat &= USBHS_USBINTR; // mask away unwanted interrupts
Serial.print("isr:");
Serial.println();
Serial.print("ISR: ");
Serial.print(stat, HEX); Serial.print(stat, HEX);
Serial.println(); Serial.println();
if (stat & USBHS_USBSTS_UI) Serial.println(" USB Interrupt");
if (stat & USBHS_USBSTS_UEI) Serial.println(" USB Error");
if (stat & USBHS_USBSTS_PCI) Serial.println(" Port Change");
if (stat & USBHS_USBSTS_FRI) Serial.println(" Frame List Rollover");
if (stat & USBHS_USBSTS_SEI) Serial.println(" System Error");
if (stat & USBHS_USBSTS_AAI) Serial.println(" Async Advance (doorbell)");
if (stat & USBHS_USBSTS_URI) Serial.println(" Reset Recv");
if (stat & USBHS_USBSTS_SRI) Serial.println(" SOF");
if (stat & USBHS_USBSTS_SLI) Serial.println(" Suspend");
if (stat & USBHS_USBSTS_HCH) Serial.println(" Host Halted");
if (stat & USBHS_USBSTS_RCL) Serial.println(" Reclamation");
if (stat & USBHS_USBSTS_PS) Serial.println(" Periodic Sched En");
if (stat & USBHS_USBSTS_AS) Serial.println(" Async Sched En");
if (stat & USBHS_USBSTS_NAKI) Serial.println(" NAK");
if (stat & USBHS_USBSTS_UAI) Serial.println(" USB Async");
if (stat & USBHS_USBSTS_UPI) Serial.println(" USB Periodic");
if (stat & USBHS_USBSTS_TI0) Serial.println(" Timer0");
if (stat & USBHS_USBSTS_TI1) Serial.println(" Timer1");


if (stat & USBHS_USBSTS_PCI) { // port change detected if (stat & USBHS_USBSTS_PCI) { // port change detected
const uint32_t portstat = USBHS_PORTSC1; const uint32_t portstat = USBHS_PORTSC1;
USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN;
stat &= ~USBHS_USBSTS_TI0; stat &= ~USBHS_USBSTS_TI0;
} }
// TODO: should ENHOSTDISCONDETECT be set? K66 ref, page 1701
} else { } else {
Serial.println(" disconnect"); Serial.println(" disconnect");
port_state = PORT_STATE_DISCONNECTED; port_state = PORT_STATE_DISCONNECTED;
dev->setup.bRequest = 0x06; // 6=GET_DESCRIPTOR dev->setup.bRequest = 0x06; // 6=GET_DESCRIPTOR
dev->setup.wValue = 0x0100; dev->setup.wValue = 0x0100;
dev->setup.wIndex = 0x0000; dev->setup.wIndex = 0x0000;
dev->setup.wLength = 8;
dev->setup.wLength = 0;
Transfer_t *transfer = new_Transfer(dev->control_pipe, buffer, 8); Transfer_t *transfer = new_Transfer(dev->control_pipe, buffer, 8);
if (transfer) queue_Transfer(transfer); if (transfer) queue_Transfer(transfer);


return dev; return dev;
} }




static uint32_t QH_capabilities1(uint32_t nak_count_reload, uint32_t control_endpoint_flag, static uint32_t QH_capabilities1(uint32_t nak_count_reload, uint32_t control_endpoint_flag,
uint32_t max_packet_length, uint32_t head_of_list, uint32_t data_toggle_control, uint32_t max_packet_length, uint32_t head_of_list, uint32_t data_toggle_control,
uint32_t speed, uint32_t endpoint_number, uint32_t inactivate, uint32_t address) uint32_t speed, uint32_t endpoint_number, uint32_t inactivate, uint32_t address)
(split_completion_mask << 8) | (interrupt_schedule_mask << 0) ); (split_completion_mask << 8) | (interrupt_schedule_mask << 0) );
} }




Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t direction, Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t direction,
uint32_t max_packet_len) uint32_t max_packet_len)
{ {
pipe->qh.buffer[2] = 0; pipe->qh.buffer[2] = 0;
pipe->qh.buffer[3] = 0; pipe->qh.buffer[3] = 0;
pipe->qh.buffer[4] = 0; pipe->qh.buffer[4] = 0;
if (pipe->type == 0) {
pipe->active = 0;
pipe->direction = direction;
pipe->type = type;
if (type == 0) {
// control // control
if (dev->speed < 2) c = 1; if (dev->speed < 2) c = 1;
dtc = 1; dtc = 1;
} else if (pipe->type == 2) {
} else if (type == 2) {
// bulk // bulk
} else if (pipe->type == 3) {
} else if (type == 3) {
// interrupt // interrupt
} }
pipe->qh.capabilities[0] = QH_capabilities1(15, c, max_packet_len, 0, pipe->qh.capabilities[0] = QH_capabilities1(15, c, max_packet_len, 0,
dtc, dev->speed, endpoint, 0, dev->address); dtc, dev->speed, endpoint, 0, dev->address);
pipe->qh.capabilities[1] = QH_capabilities2(1, dev->hub_port, pipe->qh.capabilities[1] = QH_capabilities2(1, dev->hub_port,
dev->hub_address, 0, 0); dev->hub_address, 0, 0);
if (pipe->type == 0 || pipe->type == 2) {
#if 0
if (type == 0 || type == 2) {
// control or bulk: add to async queue // control or bulk: add to async queue
Pipe_t *list = (Pipe_t *)USBHS_ASYNCLISTADDR; Pipe_t *list = (Pipe_t *)USBHS_ASYNCLISTADDR;
if (list == NULL) { if (list == NULL) {
list->qh.horizontal_link = (uint32_t)&(pipe->qh) | 2; list->qh.horizontal_link = (uint32_t)&(pipe->qh) | 2;
Serial.println(" added to async list"); Serial.println(" added to async list");
} }
} else if (pipe->type == 3) {
pipe->active = 1;
} else if (type == 3) {
// interrupt: add to periodic schedule // interrupt: add to periodic schedule
// TODO: link it into the periodic table // TODO: link it into the periodic table
} }
#endif
return pipe; return pipe;
} }


{ {
t->qtd.alt_next = 1; // 1=terminate t->qtd.alt_next = 1; // 1=terminate
if (data01) data01 = 0x80000000; if (data01) data01 = 0x80000000;
t->qtd.token = data01 | (len << 16) | (irq ? 0x8000 : 0) | (pid << 8);
t->qtd.token = data01 | (len << 16) | (irq ? 0x8000 : 0) | (pid << 8) | 0x8000;
uint32_t addr = (uint32_t)buf; uint32_t addr = (uint32_t)buf;
t->qtd.buffer[0] = addr; t->qtd.buffer[0] = addr;
addr &= 0xFFFFF000; addr &= 0xFFFFF000;
void queue_Transfer(Transfer_t *transfer) void queue_Transfer(Transfer_t *transfer)
{ {
Serial.println("queue_Transfer"); Serial.println("queue_Transfer");
Pipe_t *pipe = transfer->pipe;
Transfer_t *last = (Transfer_t *)(pipe->qh.next);
if ((uint32_t)last & 1) {
pipe->qh.next = (uint32_t)transfer;
Serial.println(" first on QH");
volatile Pipe_t *pipe = transfer->pipe;

if (!pipe->active) {
if (pipe->type == 0 || pipe->type == 2) {
// control or bulk: add to async queue
pipe->qh.next = (uint32_t)transfer;
volatile Pipe_t *list = (Pipe_t *)USBHS_ASYNCLISTADDR;
if (list == NULL) {
Serial.println(" first in async list, with qTD");
pipe->qh.capabilities[0] |= 0x8000; // H bit
pipe->qh.horizontal_link = (uint32_t)(&(pipe->qh)) | 2; // 2=QH
USBHS_ASYNCLISTADDR = (uint32_t)pipe;
Serial.println(USBHS_USBSTS & USBHS_USBSTS_AS, HEX);
Serial.println(USBHS_USBCMD & USBHS_USBCMD_ASE, HEX);
//USBHS_USBCMD |= USBHS_USBCMD_IAA;
USBHS_USBCMD |= USBHS_USBCMD_ASE; // enable async schedule
uint32_t count=0;
while (!(USBHS_USBSTS & USBHS_USBSTS_AS)) count++;
Serial.print(" waited ");
Serial.println(count);
Serial.println(USBHS_USBCMD & USBHS_USBCMD_ASE, HEX);
Serial.println(USBHS_USBSTS & USBHS_USBSTS_AS, HEX);
} else {
// EHCI 1.0: section 4.8.1, page 72
pipe->qh.horizontal_link = list->qh.horizontal_link;
list->qh.horizontal_link = (uint32_t)&(pipe->qh) | 2;
Serial.println(" added to async list, with qTD");
}
pipe->active = 1;
} else if (pipe->type == 3) {
// interrupt: add to periodic schedule
// TODO: link it into the periodic table
}
} else { } else {
while ((last->qtd.next & 1) == 0) last = (Transfer_t *)(last->qtd.next);
last->qtd.next = (uint32_t)transfer;
Serial.println(" added to qTD list");
Transfer_t *last = (Transfer_t *)(pipe->qh.next);
if ((uint32_t)last & 1) {
pipe->qh.next = (uint32_t)transfer;
Serial.println(" first on QH");
} else {
while ((last->qtd.next & 1) == 0) last = (Transfer_t *)(last->qtd.next);
last->qtd.next = (uint32_t)transfer;
Serial.println(" added to qTD list");
}
} }
} }



Loading…
Cancel
Save