From 6b05089700bdd19d081583bb75e55ff865f29efe Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Fri, 28 Jun 2013 21:30:46 -0400 Subject: [PATCH 01/48] usb: Add usb_endpoint_append_td This implements the procedure for adding a TD to the end of an active queue described in UM10503 Section 23.10.11.3. --- firmware/hackrf_usb/usb.c | 33 +++++++++++++++++++++++++++++++++ firmware/hackrf_usb/usb.h | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 8396e1bf..02fb81c3 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -195,6 +195,39 @@ void usb_endpoint_prime( USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number); } } + +// Schedule an already filled-up transfer descriptor for execution on +// the given endpoint. Note that this requires that one knows the tail +// of the endpoint's TD queue +void usb_endpoint_append_td( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const tail_td, + usb_transfer_descriptor_t* const new_td +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + bool done; + + tail_td->next_dtd_pointer = new_td; + + do { + if( usb_endpoint_is_in(endpoint->address) ) { + if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number) ) + return; + } else { + if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number) ) + return; + } + + USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; + done = usb_endpoint_is_ready(endpoint); + } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW)); + + USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW; + if(!done) { + usb_endpoint_prime(endpoint, new_td); + } +} + /* static bool usb_endpoint_is_priming( const usb_endpoint_t* const endpoint diff --git a/firmware/hackrf_usb/usb.h b/firmware/hackrf_usb/usb.h index 4b1d50f4..94372e0c 100644 --- a/firmware/hackrf_usb/usb.h +++ b/firmware/hackrf_usb/usb.h @@ -92,4 +92,10 @@ void usb_endpoint_prime( usb_transfer_descriptor_t* const first_td ); +void usb_endpoint_append_td( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const tail_td, + usb_transfer_descriptor_t* const new_td +); + #endif//__USB_H__ From 42b73919180eebbb5930eacfaaafc62bdc8a3dae Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Fri, 28 Jun 2013 21:53:59 -0400 Subject: [PATCH 02/48] usb: Begin shuffling transfer management to usb_queue --- firmware/hackrf_usb/Makefile | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb.c | 43 ------------- firmware/hackrf_usb/usb.h | 10 --- firmware/hackrf_usb/usb_queue.c | 71 ++++++++++++++++++++++ firmware/hackrf_usb/usb_queue.h | 46 ++++++++++++++ firmware/hackrf_usb/usb_standard_request.c | 1 + 7 files changed, 120 insertions(+), 53 deletions(-) create mode 100644 firmware/hackrf_usb/usb_queue.c create mode 100644 firmware/hackrf_usb/usb_queue.h diff --git a/firmware/hackrf_usb/Makefile b/firmware/hackrf_usb/Makefile index 3d2b4d53..20a97295 100644 --- a/firmware/hackrf_usb/Makefile +++ b/firmware/hackrf_usb/Makefile @@ -27,6 +27,7 @@ SRC = $(BINARY).c \ usb_request.c \ usb_standard_request.c \ usb_descriptor.c \ + usb_queue.c \ ../common/fault_handler.c \ ../common/hackrf_core.c \ ../common/sgpio.c \ diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index a175ea3d..439f88cf 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -39,6 +39,7 @@ #include "usb.h" #include "usb_type.h" +#include "usb_queue.h" #include "usb_request.h" #include "usb_descriptor.h" #include "usb_standard_request.h" diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 02fb81c3..0487ef43 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -34,10 +34,8 @@ usb_device_t* usb_device_usb0 = 0; usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); -usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64); #define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) -#define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) usb_queue_head_t* usb_queue_head( const uint_fast8_t endpoint_address @@ -45,12 +43,6 @@ usb_queue_head_t* usb_queue_head( return &usb_qh[USB_QH_INDEX(endpoint_address)]; } -usb_transfer_descriptor_t* usb_transfer_descriptor( - const uint_fast8_t endpoint_address -) { - return &usb_td[USB_TD_INDEX(endpoint_address)]; -} - static usb_endpoint_t* usb_endpoint_from_address( const uint_fast8_t endpoint_address ) { @@ -543,41 +535,6 @@ void usb_endpoint_init( usb_endpoint_enable(endpoint); } -void usb_endpoint_schedule( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length -) { - usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address); - - // Ensure that endpoint is ready to be primed. - // It may have been flushed due to an aborted transaction. - // TODO: This should be preceded by a flush? - while( usb_endpoint_is_ready(endpoint) ); - - // Configure a transfer. - td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - td->total_bytes = - USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) - | USB_TD_DTD_TOKEN_IOC - | USB_TD_DTD_TOKEN_MULTO(0) - | USB_TD_DTD_TOKEN_STATUS_ACTIVE - ; - td->buffer_pointer_page[0] = (uint32_t)data; - td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; - td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; - td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; - td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; - - usb_endpoint_prime(endpoint, td); -} - -void usb_endpoint_schedule_ack( - const usb_endpoint_t* const endpoint -) { - usb_endpoint_schedule(endpoint, 0, 0); -} - static void usb_check_for_setup_events() { const uint32_t endptsetupstat = usb_get_endpoint_setup_status(); if( endptsetupstat ) { diff --git a/firmware/hackrf_usb/usb.h b/firmware/hackrf_usb/usb.h index 94372e0c..7d64f358 100644 --- a/firmware/hackrf_usb/usb.h +++ b/firmware/hackrf_usb/usb.h @@ -61,16 +61,6 @@ void usb_endpoint_init( const usb_endpoint_t* const endpoint ); -void usb_endpoint_schedule( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length -); - -void usb_endpoint_schedule_ack( - const usb_endpoint_t* const endpoint -); - void usb_endpoint_stall( const usb_endpoint_t* const endpoint ); diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c new file mode 100644 index 00000000..8be95a22 --- /dev/null +++ b/firmware/hackrf_usb/usb_queue.c @@ -0,0 +1,71 @@ +/* + * Copyright 2012 Jared Boone + * Copyright 2013 Ben Gamari + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "usb.h" + +usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64); + +#define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) + +usb_transfer_descriptor_t* usb_transfer_descriptor( + const uint_fast8_t endpoint_address +) { + return &usb_td[USB_TD_INDEX(endpoint_address)]; +} + +void usb_endpoint_schedule( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +) { + usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address); + + // Ensure that endpoint is ready to be primed. + // It may have been flushed due to an aborted transaction. + // TODO: This should be preceded by a flush? + while( usb_endpoint_is_ready(endpoint) ); + + // Configure a transfer. + td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; + td->total_bytes = + USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) + | USB_TD_DTD_TOKEN_IOC + | USB_TD_DTD_TOKEN_MULTO(0) + | USB_TD_DTD_TOKEN_STATUS_ACTIVE + ; + td->buffer_pointer_page[0] = (uint32_t)data; + td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; + td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; + td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; + td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; + + usb_endpoint_prime(endpoint, td); +} + +void usb_endpoint_schedule_ack( + const usb_endpoint_t* const endpoint +) { + usb_endpoint_schedule(endpoint, 0, 0); +} diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h new file mode 100644 index 00000000..f07b8146 --- /dev/null +++ b/firmware/hackrf_usb/usb_queue.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012 Jared Boone + * Copyright 2013 Ben Gamari + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_QUEUE_H__ +#define __USB_QUEUE_H__ + +#include + +#include "usb_type.h" + +void usb_endpoint_schedule( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +); + +void usb_endpoint_schedule_ack( + const usb_endpoint_t* const endpoint +); + +void usb_endpoint_schedule( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +); + +#endif//__USB_QUEUE_H__ diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index cfb58ee0..59991ef1 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -27,6 +27,7 @@ #include "usb.h" #include "usb_type.h" #include "usb_descriptor.h" +#include "usb_queue.h" const uint8_t* usb_endpoint_descriptor( const usb_endpoint_t* const endpoint From e6bf90af23548684e247e1e674898e3a0053978a Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 2 Jul 2013 19:31:51 -0400 Subject: [PATCH 03/48] usb: Shuffle endpoint_schedule into endpoint_schedule_wait --- firmware/hackrf_usb/usb.c | 28 ++++++++++++++++++++++++++++ firmware/hackrf_usb/usb_queue.c | 28 +++++----------------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 0487ef43..c057b5c3 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -188,6 +188,34 @@ void usb_endpoint_prime( } } +void usb_endpoint_schedule_wait( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const td, + void* const data, + const uint32_t maximum_length +) { + // Ensure that endpoint is ready to be primed. + // It may have been flushed due to an aborted transaction. + // TODO: This should be preceded by a flush? + while( usb_endpoint_is_ready(endpoint) ); + + // Configure a transfer. + td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; + td->total_bytes = + USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) + | USB_TD_DTD_TOKEN_IOC + | USB_TD_DTD_TOKEN_MULTO(0) + | USB_TD_DTD_TOKEN_STATUS_ACTIVE + ; + td->buffer_pointer_page[0] = (uint32_t)data; + td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; + td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; + td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; + td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; + + usb_endpoint_prime(endpoint, td); +} + // Schedule an already filled-up transfer descriptor for execution on // the given endpoint. Note that this requires that one knows the tail // of the endpoint's TD queue diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 8be95a22..5792bcae 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -40,30 +40,12 @@ void usb_endpoint_schedule( void* const data, const uint32_t maximum_length ) { - usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address); - - // Ensure that endpoint is ready to be primed. - // It may have been flushed due to an aborted transaction. - // TODO: This should be preceded by a flush? - while( usb_endpoint_is_ready(endpoint) ); - - // Configure a transfer. - td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - td->total_bytes = - USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) - | USB_TD_DTD_TOKEN_IOC - | USB_TD_DTD_TOKEN_MULTO(0) - | USB_TD_DTD_TOKEN_STATUS_ACTIVE - ; - td->buffer_pointer_page[0] = (uint32_t)data; - td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; - td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; - td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; - td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; - - usb_endpoint_prime(endpoint, td); + usb_endpoint_schedule_wait(endpoint, + usb_transfer_descriptor(endpoint->address), + data, + maximum_length); } - + void usb_endpoint_schedule_ack( const usb_endpoint_t* const endpoint ) { From 6142c828df49eebf4db418cb963dad964f20ab3b Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 2 Jul 2013 22:39:26 -0400 Subject: [PATCH 04/48] usb: Refactor queue management --- firmware/hackrf_usb/usb.c | 27 ++-- firmware/hackrf_usb/usb.h | 7 +- firmware/hackrf_usb/usb_queue.c | 139 +++++++++++++++++++-- firmware/hackrf_usb/usb_queue.h | 22 +++- firmware/hackrf_usb/usb_standard_request.c | 12 +- 5 files changed, 166 insertions(+), 41 deletions(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index c057b5c3..14a94397 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -188,38 +188,27 @@ void usb_endpoint_prime( } } +// Schedule an already filled-in transfer descriptor for execution on +// the given endpoint, waiting until the endpoint has finished. void usb_endpoint_schedule_wait( const usb_endpoint_t* const endpoint, - usb_transfer_descriptor_t* const td, - void* const data, - const uint32_t maximum_length + usb_transfer_descriptor_t* const td ) { // Ensure that endpoint is ready to be primed. // It may have been flushed due to an aborted transaction. // TODO: This should be preceded by a flush? while( usb_endpoint_is_ready(endpoint) ); - // Configure a transfer. td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - td->total_bytes = - USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) - | USB_TD_DTD_TOKEN_IOC - | USB_TD_DTD_TOKEN_MULTO(0) - | USB_TD_DTD_TOKEN_STATUS_ACTIVE - ; - td->buffer_pointer_page[0] = (uint32_t)data; - td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; - td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; - td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; - td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; usb_endpoint_prime(endpoint, td); } -// Schedule an already filled-up transfer descriptor for execution on -// the given endpoint. Note that this requires that one knows the tail -// of the endpoint's TD queue -void usb_endpoint_append_td( +// Schedule an already filled-in transfer descriptor for execution on +// the given endpoint, appending to the end of the endpoint's queue if +// there are pending TDs. Note that this requires that one knows the +// tail of the endpoint's TD queue +void usb_endpoint_schedule_append( const usb_endpoint_t* const endpoint, usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const new_td diff --git a/firmware/hackrf_usb/usb.h b/firmware/hackrf_usb/usb.h index 7d64f358..a6fa6a92 100644 --- a/firmware/hackrf_usb/usb.h +++ b/firmware/hackrf_usb/usb.h @@ -82,7 +82,12 @@ void usb_endpoint_prime( usb_transfer_descriptor_t* const first_td ); -void usb_endpoint_append_td( +void usb_endpoint_schedule_wait( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const td +); + +void usb_endpoint_schedule_append( const usb_endpoint_t* const endpoint, usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const new_td diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 5792bcae..0fc833d1 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -22,32 +22,145 @@ #include #include +#include #include "usb.h" +#include "usb_queue.h" -usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64); +struct _usb_transfer_t { + struct _usb_transfer_t* next; + usb_transfer_descriptor_t td ATTR_ALIGNED(64); + unsigned int actual_length; + usb_endpoint_t* endpoint; + bool finished; + transfer_completion_cb completion_cb; +}; -#define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) +usb_transfer_t transfer_pool[16]; -usb_transfer_descriptor_t* usb_transfer_descriptor( - const uint_fast8_t endpoint_address -) { - return &usb_td[USB_TD_INDEX(endpoint_address)]; +// Available transfer list +usb_transfer_t* free_transfers; + +#define USB_ENDPOINT_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) + +// Pending transfer heads +usb_transfer_t* endpoint_transfers[12] = {}; + +void init_transfers() { + usb_transfer_t* t = &transfer_pool[0]; + free_transfers = t; + for (unsigned int i=0; i < sizeof(transfer_pool) / sizeof(usb_transfer_t); i++, t++) { + t->next = t+1; + } + t->next = NULL; } -void usb_endpoint_schedule( +static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) { + return (endpoint_address & 0x80) ? true : false; +} + +#if 0 +static usb_transfer_t* usb_transfer( + const uint_fast8_t endpoint_address +) { + return endpoint_transfers[USB_ENDPOINT_INDEX(endpoint_address)]; +} +#endif + +static void fill_in_transfer(usb_transfer_t* transfer, + void* const data, + const uint32_t maximum_length +) { + usb_transfer_descriptor_t* const td = &transfer->td; + + // Configure a transfer. + td->total_bytes = + USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) + | USB_TD_DTD_TOKEN_IOC + | USB_TD_DTD_TOKEN_MULTO(0) + | USB_TD_DTD_TOKEN_STATUS_ACTIVE + ; + td->buffer_pointer_page[0] = (uint32_t)data; + td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; + td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; + td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; + td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; +} + +static usb_transfer_t* allocate_transfer() +{ + while (free_transfers == NULL); + //disable_irqs(); // FIXME + usb_transfer_t* const transfer = free_transfers; + free_transfers = transfer->next; + //enable_irqs(); + transfer->finished = false; + return transfer; +} + +static void endpoint_add_transfer( + const usb_endpoint_t* const endpoint, + usb_transfer_t* const transfer +) { + uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); + //FIXME disable_irqs(); + usb_transfer_t* t = endpoint_transfers[index]; + transfer->next = NULL; + for (; t->next != NULL; t = t->next); + t->next = transfer; + //enable_irqs(); +} + +static usb_transfer_t* endpoint_pop_transfer( + const usb_endpoint_t* const endpoint +) { + uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); + //FIXME disable_irqs(); + usb_transfer_t* transfer = endpoint_transfers[index]; + endpoint_transfers[index] = transfer->next; + //enable_irqs(); + return transfer; +} + +void usb_transfer_schedule_wait( const usb_endpoint_t* const endpoint, void* const data, const uint32_t maximum_length ) { - usb_endpoint_schedule_wait(endpoint, - usb_transfer_descriptor(endpoint->address), - data, - maximum_length); + usb_transfer_t* const transfer = allocate_transfer(); + fill_in_transfer(transfer, data, maximum_length); + endpoint_add_transfer(endpoint, transfer); + usb_endpoint_schedule_wait(endpoint, &transfer->td); +} + +void usb_transfer_schedule_append( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +) { + usb_transfer_t* const transfer = allocate_transfer(); + uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); + fill_in_transfer(transfer, data, maximum_length); + // TODO: disable_interrupts(); + usb_transfer_t* tail = endpoint_transfers[index]; + for (; tail->next != NULL; tail = tail->next); + endpoint_add_transfer(endpoint, transfer); + usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); + //enable_interrupts(); } -void usb_endpoint_schedule_ack( +void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ) { - usb_endpoint_schedule(endpoint, 0, 0); + usb_transfer_schedule_wait(endpoint, 0, 0); +} + +void transfer_complete(const usb_endpoint_t* const endpoint) +{ + usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); + unsigned int transferred = transfer->actual_length - transfer->td.total_bytes; + if (transfer->completion_cb) + transfer->completion_cb(transfer, transferred); + else if (usb_endpoint_is_in(transfer->endpoint->address)) + transfer->finished = true; } diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index f07b8146..5e10b33e 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -27,20 +27,38 @@ #include "usb_type.h" +typedef struct _usb_transfer_t usb_transfer_t; + +typedef void (*transfer_completion_cb)(struct _usb_transfer_t*, unsigned int); + void usb_endpoint_schedule( const usb_endpoint_t* const endpoint, void* const data, const uint32_t maximum_length ); -void usb_endpoint_schedule_ack( +void usb_transfer_schedule_wait( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +); + +void usb_transfer_schedule_append( + const usb_endpoint_t* const endpoint, + void* const data, + const uint32_t maximum_length +); + +void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ); -void usb_endpoint_schedule( +void usb_transfer_schedule( const usb_endpoint_t* const endpoint, void* const data, const uint32_t maximum_length ); +void init_transfers(void); + #endif//__USB_QUEUE_H__ diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index 59991ef1..db9a0940 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -115,12 +115,12 @@ static usb_request_status_t usb_send_descriptor( if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) { descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2]; } - usb_endpoint_schedule( + usb_transfer_schedule_wait( endpoint->in, descriptor_data, (setup_length > descriptor_length) ? descriptor_length : setup_length ); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -196,7 +196,7 @@ static usb_request_status_t usb_standard_request_set_address_setup( usb_endpoint_t* const endpoint ) { usb_set_address_deferred(endpoint->device, endpoint->setup.value_l); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } @@ -232,7 +232,7 @@ static usb_request_status_t usb_standard_request_set_configuration_setup( // TODO: Should this be done immediately? usb_set_address_immediate(endpoint->device, 0); } - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } else { return USB_REQUEST_STATUS_STALL; @@ -266,8 +266,8 @@ static usb_request_status_t usb_standard_request_get_configuration_setup( if( endpoint->device->configuration ) { endpoint->buffer[0] = endpoint->device->configuration->number; } - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { return USB_REQUEST_STATUS_STALL; From f015fd7640a204f90a22bd3c8792e7df004c9956 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 13:38:59 -0400 Subject: [PATCH 05/48] usb: Things enumerate --- firmware/hackrf_usb/usb_queue.c | 18 ++++++++++++------ firmware/hackrf_usb/usb_queue.h | 6 +++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 0fc833d1..ed0e4a6e 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "usb.h" #include "usb_queue.h" @@ -46,10 +47,10 @@ usb_transfer_t* free_transfers; // Pending transfer heads usb_transfer_t* endpoint_transfers[12] = {}; -void init_transfers() { +void usb_queue_init() { usb_transfer_t* t = &transfer_pool[0]; free_transfers = t; - for (unsigned int i=0; i < sizeof(transfer_pool) / sizeof(usb_transfer_t); i++, t++) { + for (unsigned int i=0; i < sizeof(transfer_pool) / sizeof(usb_transfer_t) - 1; i++, t++) { t->next = t+1; } t->next = NULL; @@ -104,10 +105,14 @@ static void endpoint_add_transfer( ) { uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); //FIXME disable_irqs(); - usb_transfer_t* t = endpoint_transfers[index]; transfer->next = NULL; - for (; t->next != NULL; t = t->next); - t->next = transfer; + if (endpoint_transfers[index] != NULL) { + usb_transfer_t* t = endpoint_transfers[index]; + for (; t->next != NULL; t = t->next); + t->next = transfer; + } else { + endpoint_transfers[index] = transfer; + } //enable_irqs(); } @@ -117,6 +122,7 @@ static usb_transfer_t* endpoint_pop_transfer( uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); //FIXME disable_irqs(); usb_transfer_t* transfer = endpoint_transfers[index]; + assert(transfer != NULL); endpoint_transfers[index] = transfer->next; //enable_irqs(); return transfer; @@ -155,7 +161,7 @@ void usb_transfer_schedule_ack( usb_transfer_schedule_wait(endpoint, 0, 0); } -void transfer_complete(const usb_endpoint_t* const endpoint) +void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) { usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); unsigned int transferred = transfer->actual_length - transfer->td.total_bytes; diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index 5e10b33e..3963f15d 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -59,6 +59,10 @@ void usb_transfer_schedule( const uint32_t maximum_length ); -void init_transfers(void); +void usb_queue_init(void); + +void usb_queue_transfer_complete( + usb_endpoint_t* const endpoint +); #endif//__USB_QUEUE_H__ From bd4e39d3796ec49c68bb06b5fd41cfddc8f300b3 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:08:46 -0400 Subject: [PATCH 06/48] usb_queue: Add completion_cb arguments --- firmware/hackrf_usb/usb_queue.c | 10 +++++++--- firmware/hackrf_usb/usb_queue.h | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index ed0e4a6e..91511885 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -131,10 +131,12 @@ static usb_transfer_t* endpoint_pop_transfer( void usb_transfer_schedule_wait( const usb_endpoint_t* const endpoint, void* const data, - const uint32_t maximum_length + const uint32_t maximum_length, + const transfer_completion_cb completion_cb ) { usb_transfer_t* const transfer = allocate_transfer(); fill_in_transfer(transfer, data, maximum_length); + transfer->completion_cb = completion_cb; endpoint_add_transfer(endpoint, transfer); usb_endpoint_schedule_wait(endpoint, &transfer->td); } @@ -142,11 +144,13 @@ void usb_transfer_schedule_wait( void usb_transfer_schedule_append( const usb_endpoint_t* const endpoint, void* const data, - const uint32_t maximum_length + const uint32_t maximum_length, + const transfer_completion_cb completion_cb ) { usb_transfer_t* const transfer = allocate_transfer(); uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); fill_in_transfer(transfer, data, maximum_length); + transfer->completion_cb = completion_cb; // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; for (; tail->next != NULL; tail = tail->next); @@ -158,7 +162,7 @@ void usb_transfer_schedule_append( void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ) { - usb_transfer_schedule_wait(endpoint, 0, 0); + usb_transfer_schedule_wait(endpoint, 0, 0, NULL); } void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index 3963f15d..cec51fb3 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -40,13 +40,15 @@ void usb_endpoint_schedule( void usb_transfer_schedule_wait( const usb_endpoint_t* const endpoint, void* const data, - const uint32_t maximum_length + const uint32_t maximum_length, + const transfer_completion_cb completion_cb ); void usb_transfer_schedule_append( const usb_endpoint_t* const endpoint, void* const data, - const uint32_t maximum_length + const uint32_t maximum_length, + const transfer_completion_cb completion_cb ); void usb_transfer_schedule_ack( From c62798d31fa4114c3ae23bb43d5496fe7b134abd Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:18:06 -0400 Subject: [PATCH 07/48] usb_queue: Kill old declaration --- firmware/hackrf_usb/usb_queue.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index cec51fb3..1498be46 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -55,12 +55,6 @@ void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ); -void usb_transfer_schedule( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length -); - void usb_queue_init(void); void usb_queue_transfer_complete( From dfdfad2bf018d38aa092ba813f7bb2ade3b06fbb Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:18:28 -0400 Subject: [PATCH 08/48] hackrf_usb: Port to usb_queue --- firmware/hackrf_usb/hackrf_usb.c | 76 +++++++++++----------- firmware/hackrf_usb/usb_standard_request.c | 5 +- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 439f88cf..ff952b69 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -353,7 +353,7 @@ usb_request_status_t usb_vendor_request_set_transceiver_mode( case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_TX: set_transceiver_mode(endpoint->setup.value); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; default: return USB_REQUEST_STATUS_STALL; @@ -371,7 +371,7 @@ usb_request_status_t usb_vendor_request_write_max2837( if( endpoint->setup.index < MAX2837_NUM_REGS ) { if( endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE ) { max2837_reg_write(endpoint->setup.index, endpoint->setup.value); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } } @@ -390,8 +390,8 @@ usb_request_status_t usb_vendor_request_read_max2837( const uint16_t value = max2837_reg_read(endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 2, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -408,7 +408,7 @@ usb_request_status_t usb_vendor_request_write_si5351c( if( endpoint->setup.index < 256 ) { if( endpoint->setup.value < 256 ) { si5351c_write_single(endpoint->setup.index, endpoint->setup.value); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } } @@ -426,8 +426,8 @@ usb_request_status_t usb_vendor_request_read_si5351c( if( endpoint->setup.index < 256 ) { const uint8_t value = si5351c_read_single(endpoint->setup.index); endpoint->buffer[0] = value; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -443,7 +443,7 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value; if( baseband_filter_bandwidth_set(bandwidth) ) { - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -461,7 +461,7 @@ usb_request_status_t usb_vendor_request_write_rffc5071( if( endpoint->setup.index < RFFC5071_NUM_REGS ) { rffc5071_reg_write(endpoint->setup.index, endpoint->setup.value); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -482,8 +482,8 @@ usb_request_status_t usb_vendor_request_read_rffc5071( value = rffc5071_reg_read(endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 2, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -501,7 +501,7 @@ usb_request_status_t usb_vendor_request_erase_spiflash( w25q80bv_setup(); /* only chip erase is implemented */ w25q80bv_chip_erase(); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); //FIXME probably should undo w25q80bv_setup() } return USB_REQUEST_STATUS_OK; @@ -522,7 +522,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - usb_endpoint_schedule(endpoint->out, &spiflash_buffer[0], len); + usb_transfer_schedule_wait(endpoint->out, &spiflash_buffer[0], len, NULL); w25q80bv_setup(); return USB_REQUEST_STATUS_OK; } @@ -535,7 +535,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( return USB_REQUEST_STATUS_STALL; } else { w25q80bv_program(addr, len, &spiflash_buffer[0]); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); //FIXME probably should undo w25q80bv_setup() return USB_REQUEST_STATUS_OK; } @@ -566,7 +566,7 @@ usb_request_status_t usb_vendor_request_read_spiflash( { spiflash_buffer[i] = u8_addr_pt[i]; } - usb_endpoint_schedule(endpoint->in, &spiflash_buffer[0], len); + usb_transfer_schedule_wait(endpoint->in, &spiflash_buffer[0], len, NULL); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) @@ -580,7 +580,7 @@ usb_request_status_t usb_vendor_request_read_spiflash( return USB_REQUEST_STATUS_STALL; } else { - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } } else @@ -604,7 +604,7 @@ usb_request_status_t usb_vendor_request_write_cpld( // len is limited to 64KB 16bits no overflow can happen total_len = endpoint->setup.value; len = endpoint->setup.length; - usb_endpoint_schedule(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len); + usb_transfer_schedule_wait(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -620,7 +620,7 @@ usb_request_status_t usb_vendor_request_write_cpld( // TO FIX ACK shall be not delayed so much as cpld prog can take up to 5s. if(error == 0) { - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); /* blink LED1, LED2, and LED3 on success */ while (1) @@ -642,7 +642,7 @@ usb_request_status_t usb_vendor_request_write_cpld( } }else { - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } } else @@ -656,8 +656,8 @@ usb_request_status_t usb_vendor_request_read_board_id( { if (stage == USB_TRANSFER_STAGE_SETUP) { endpoint->buffer[0] = BOARD_ID; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; } @@ -669,8 +669,8 @@ usb_request_status_t usb_vendor_request_read_version_string( if (stage == USB_TRANSFER_STAGE_SETUP) { length = (uint8_t)strlen(version_string); - usb_endpoint_schedule(endpoint->in, version_string, length); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, version_string, length, NULL); + usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; } @@ -681,13 +681,13 @@ usb_request_status_t usb_vendor_request_set_freq( { if (stage == USB_TRANSFER_STAGE_SETUP) { - usb_endpoint_schedule(endpoint->out, &set_freq_params, sizeof(set_freq_params_t)); + usb_transfer_schedule_wait(endpoint->out, &set_freq_params, sizeof(set_freq_params_t), NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { if( set_freq(set_freq_params.freq_mhz, set_freq_params.freq_hz) ) { - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -703,13 +703,13 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( { if (stage == USB_TRANSFER_STAGE_SETUP) { - usb_endpoint_schedule(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t)); + usb_transfer_schedule_wait(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t), NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { if( sample_rate_frac_set(set_sample_r_params.freq_hz * 2, set_sample_r_params.divider ) ) { - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; @@ -727,12 +727,12 @@ usb_request_status_t usb_vendor_request_set_amp_enable( case 0: switchctrl |= SWITCHCTRL_AMP_BYPASS; update_switches(); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; case 1: switchctrl &= ~SWITCHCTRL_AMP_BYPASS; update_switches(); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; default: return USB_REQUEST_STATUS_STALL; @@ -777,8 +777,8 @@ usb_request_status_t usb_vendor_request_read_partid_serialno( read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3]; length = (uint8_t)sizeof(read_partid_serialno_t); - usb_endpoint_schedule(endpoint->in, &read_partid_serialno, length); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &read_partid_serialno, length, NULL); + usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; } @@ -789,8 +789,8 @@ usb_request_status_t usb_vendor_request_set_lna_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_lna_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; @@ -802,8 +802,8 @@ usb_request_status_t usb_vendor_request_set_vga_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_vga_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; @@ -815,8 +815,8 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_txvga_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1); - usb_endpoint_schedule_ack(endpoint->out); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; @@ -828,7 +828,7 @@ usb_request_status_t usb_vendor_request_set_if_freq( if( stage == USB_TRANSFER_STAGE_SETUP ) { MAX2837_FREQ_NOMINAL_HZ = (uint32_t)endpoint->setup.index * 1000 * 1000; set_freq(freq_mhz_cache, freq_hz_cache); - usb_endpoint_schedule_ack(endpoint->in); + usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; } diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index db9a0940..78ae7f3d 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -118,7 +118,8 @@ static usb_request_status_t usb_send_descriptor( usb_transfer_schedule_wait( endpoint->in, descriptor_data, - (setup_length > descriptor_length) ? descriptor_length : setup_length + (setup_length > descriptor_length) ? descriptor_length : setup_length, + NULL ); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; @@ -266,7 +267,7 @@ static usb_request_status_t usb_standard_request_get_configuration_setup( if( endpoint->device->configuration ) { endpoint->buffer[0] = endpoint->device->configuration->number; } - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1); + usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { From ac29621a36d87171b23d16551b188a31a6ee8b37 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:32:04 -0400 Subject: [PATCH 09/48] usb_queue: Use typedef --- firmware/hackrf_usb/usb_queue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index 1498be46..74a6323d 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -29,7 +29,7 @@ typedef struct _usb_transfer_t usb_transfer_t; -typedef void (*transfer_completion_cb)(struct _usb_transfer_t*, unsigned int); +typedef void (*transfer_completion_cb)(usb_transfer_t*, unsigned int); void usb_endpoint_schedule( const usb_endpoint_t* const endpoint, From ee46cf1fc42603a1ef0e9badd85f982e8a65297c Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:51:41 -0400 Subject: [PATCH 10/48] usb_queue: Cleanup --- firmware/hackrf_usb/usb_queue.c | 39 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 91511885..38d00f3e 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -31,9 +31,8 @@ struct _usb_transfer_t { struct _usb_transfer_t* next; usb_transfer_descriptor_t td ATTR_ALIGNED(64); - unsigned int actual_length; + unsigned int maximum_length; usb_endpoint_t* endpoint; - bool finished; transfer_completion_cb completion_cb; }; @@ -56,25 +55,13 @@ void usb_queue_init() { t->next = NULL; } -static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) { - return (endpoint_address & 0x80) ? true : false; -} - -#if 0 -static usb_transfer_t* usb_transfer( - const uint_fast8_t endpoint_address -) { - return endpoint_transfers[USB_ENDPOINT_INDEX(endpoint_address)]; -} -#endif - static void fill_in_transfer(usb_transfer_t* transfer, void* const data, const uint32_t maximum_length ) { usb_transfer_descriptor_t* const td = &transfer->td; - // Configure a transfer. + // Configure the transfer. descriptor td->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) | USB_TD_DTD_TOKEN_IOC @@ -86,8 +73,11 @@ static void fill_in_transfer(usb_transfer_t* transfer, td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; + + transfer->maximum_length = maximum_length; } +/* Allocate a transfer */ static usb_transfer_t* allocate_transfer() { while (free_transfers == NULL); @@ -95,10 +85,19 @@ static usb_transfer_t* allocate_transfer() usb_transfer_t* const transfer = free_transfers; free_transfers = transfer->next; //enable_irqs(); - transfer->finished = false; return transfer; } +/* Place a transfer in the free list */ +static void free_transfer(usb_transfer_t* const transfer) +{ + //disable_irqs(); // FIXME + transfer->next = free_transfers; + free_transfers = transfer; + //enable_irqs(); +} + +/* Add a transfer to the end of an endpoint's queue */ static void endpoint_add_transfer( const usb_endpoint_t* const endpoint, usb_transfer_t* const transfer @@ -116,6 +115,7 @@ static void endpoint_add_transfer( //enable_irqs(); } +/* Pop off the transfer at the top of an endpoint's queue */ static usb_transfer_t* endpoint_pop_transfer( const usb_endpoint_t* const endpoint ) { @@ -162,15 +162,14 @@ void usb_transfer_schedule_append( void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ) { - usb_transfer_schedule_wait(endpoint, 0, 0, NULL); + usb_transfer_schedule_wait(endpoint, 0, 0, NULL); } void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) { usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); - unsigned int transferred = transfer->actual_length - transfer->td.total_bytes; + unsigned int transferred = transfer->maximum_length - transfer->td.total_bytes; if (transfer->completion_cb) transfer->completion_cb(transfer, transferred); - else if (usb_endpoint_is_in(transfer->endpoint->address)) - transfer->finished = true; + free_transfer(transfer); } From ccfdd8350d73d50c8733a7fe18da23a85628a125 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 14:51:50 -0400 Subject: [PATCH 11/48] usb_request: Ensure control endpoint transfers get freed --- firmware/hackrf_usb/usb_request.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/hackrf_usb/usb_request.c b/firmware/hackrf_usb/usb_request.c index 25132fd4..f9226c7f 100644 --- a/firmware/hackrf_usb/usb_request.c +++ b/firmware/hackrf_usb/usb_request.c @@ -21,6 +21,7 @@ #include "usb.h" #include "usb_request.h" +#include "usb_queue.h" #include @@ -75,6 +76,7 @@ void usb_control_out_complete( } else { usb_request(endpoint, USB_TRANSFER_STAGE_DATA); } + usb_queue_transfer_complete(endpoint); } void usb_control_in_complete( @@ -87,5 +89,6 @@ void usb_control_in_complete( } else { usb_request(endpoint, USB_TRANSFER_STAGE_STATUS); } + usb_queue_transfer_complete(endpoint); } From ecd9b2e73169691391fb4d19bdcb41f92fa79eec Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:23:30 -0400 Subject: [PATCH 12/48] usb_queue: Kill usb_transfer_schedule_wait --- firmware/hackrf_usb/usb_queue.c | 27 +++++++++------------------ firmware/hackrf_usb/usb_queue.h | 9 +-------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 38d00f3e..0aa3a3c3 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -128,20 +128,7 @@ static usb_transfer_t* endpoint_pop_transfer( return transfer; } -void usb_transfer_schedule_wait( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length, - const transfer_completion_cb completion_cb -) { - usb_transfer_t* const transfer = allocate_transfer(); - fill_in_transfer(transfer, data, maximum_length); - transfer->completion_cb = completion_cb; - endpoint_add_transfer(endpoint, transfer); - usb_endpoint_schedule_wait(endpoint, &transfer->td); -} - -void usb_transfer_schedule_append( +void usb_transfer_schedule( const usb_endpoint_t* const endpoint, void* const data, const uint32_t maximum_length, @@ -153,16 +140,20 @@ void usb_transfer_schedule_append( transfer->completion_cb = completion_cb; // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; - for (; tail->next != NULL; tail = tail->next); - endpoint_add_transfer(endpoint, transfer); - usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); + if (tail == NULL) { + usb_endpoint_schedule_wait(endpoint, &transfer->td); + } else { + for (; tail->next != NULL; tail = tail->next); + endpoint_add_transfer(endpoint, transfer); + usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); + } //enable_interrupts(); } void usb_transfer_schedule_ack( const usb_endpoint_t* const endpoint ) { - usb_transfer_schedule_wait(endpoint, 0, 0, NULL); + usb_transfer_schedule(endpoint, 0, 0, NULL); } void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index 74a6323d..f6dc0203 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -37,14 +37,7 @@ void usb_endpoint_schedule( const uint32_t maximum_length ); -void usb_transfer_schedule_wait( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length, - const transfer_completion_cb completion_cb -); - -void usb_transfer_schedule_append( +void usb_transfer_schedule( const usb_endpoint_t* const endpoint, void* const data, const uint32_t maximum_length, From 96f8621ad99238f06f33d1dbec06e95513f5cc66 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:25:17 -0400 Subject: [PATCH 13/48] hackrf_usb: Port things away from schedule_wait --- firmware/hackrf_usb/hackrf_usb.c | 28 +++++++++++----------- firmware/hackrf_usb/usb_standard_request.c | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index ff952b69..14d1722b 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -390,7 +390,7 @@ usb_request_status_t usb_vendor_request_read_max2837( const uint16_t value = max2837_reg_read(endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 2, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 2, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -426,7 +426,7 @@ usb_request_status_t usb_vendor_request_read_si5351c( if( endpoint->setup.index < 256 ) { const uint8_t value = si5351c_read_single(endpoint->setup.index); endpoint->buffer[0] = value; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -482,7 +482,7 @@ usb_request_status_t usb_vendor_request_read_rffc5071( value = rffc5071_reg_read(endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 2, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 2, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -522,7 +522,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - usb_transfer_schedule_wait(endpoint->out, &spiflash_buffer[0], len, NULL); + usb_transfer_schedule(endpoint->out, &spiflash_buffer[0], len, NULL); w25q80bv_setup(); return USB_REQUEST_STATUS_OK; } @@ -566,7 +566,7 @@ usb_request_status_t usb_vendor_request_read_spiflash( { spiflash_buffer[i] = u8_addr_pt[i]; } - usb_transfer_schedule_wait(endpoint->in, &spiflash_buffer[0], len, NULL); + usb_transfer_schedule(endpoint->in, &spiflash_buffer[0], len, NULL); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) @@ -604,7 +604,7 @@ usb_request_status_t usb_vendor_request_write_cpld( // len is limited to 64KB 16bits no overflow can happen total_len = endpoint->setup.value; len = endpoint->setup.length; - usb_transfer_schedule_wait(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len, NULL); + usb_transfer_schedule(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -656,7 +656,7 @@ usb_request_status_t usb_vendor_request_read_board_id( { if (stage == USB_TRANSFER_STAGE_SETUP) { endpoint->buffer[0] = BOARD_ID; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; @@ -669,7 +669,7 @@ usb_request_status_t usb_vendor_request_read_version_string( if (stage == USB_TRANSFER_STAGE_SETUP) { length = (uint8_t)strlen(version_string); - usb_transfer_schedule_wait(endpoint->in, version_string, length, NULL); + usb_transfer_schedule(endpoint->in, version_string, length, NULL); usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; @@ -681,7 +681,7 @@ usb_request_status_t usb_vendor_request_set_freq( { if (stage == USB_TRANSFER_STAGE_SETUP) { - usb_transfer_schedule_wait(endpoint->out, &set_freq_params, sizeof(set_freq_params_t), NULL); + usb_transfer_schedule(endpoint->out, &set_freq_params, sizeof(set_freq_params_t), NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -703,7 +703,7 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( { if (stage == USB_TRANSFER_STAGE_SETUP) { - usb_transfer_schedule_wait(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t), NULL); + usb_transfer_schedule(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t), NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -777,7 +777,7 @@ usb_request_status_t usb_vendor_request_read_partid_serialno( read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3]; length = (uint8_t)sizeof(read_partid_serialno_t); - usb_transfer_schedule_wait(endpoint->in, &read_partid_serialno, length, NULL); + usb_transfer_schedule(endpoint->in, &read_partid_serialno, length, NULL); usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; @@ -789,7 +789,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_lna_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -802,7 +802,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_vga_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } @@ -815,7 +815,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_txvga_gain(endpoint->setup.index); endpoint->buffer[0] = value; - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index 78ae7f3d..43f2379f 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -115,7 +115,7 @@ static usb_request_status_t usb_send_descriptor( if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) { descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2]; } - usb_transfer_schedule_wait( + usb_transfer_schedule( endpoint->in, descriptor_data, (setup_length > descriptor_length) ? descriptor_length : setup_length, @@ -267,7 +267,7 @@ static usb_request_status_t usb_standard_request_get_configuration_setup( if( endpoint->device->configuration ) { endpoint->buffer[0] = endpoint->device->configuration->number; } - usb_transfer_schedule_wait(endpoint->in, &endpoint->buffer, 1, NULL); + usb_transfer_schedule(endpoint->in, &endpoint->buffer, 1, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { From af34a7a0416c5a8125bd99f39319e94d8c803e3f Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:35:26 -0400 Subject: [PATCH 14/48] usb: Use usb_endpoint_is_priming helper --- firmware/hackrf_usb/usb.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 14a94397..09e3d127 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -188,6 +188,17 @@ void usb_endpoint_prime( } } +static bool usb_endpoint_is_priming( + const usb_endpoint_t* const endpoint +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if( usb_endpoint_is_in(endpoint->address) ) { + return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number); + } else { + return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number); + } +} + // Schedule an already filled-in transfer descriptor for execution on // the given endpoint, waiting until the endpoint has finished. void usb_endpoint_schedule_wait( @@ -213,18 +224,13 @@ void usb_endpoint_schedule_append( usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const new_td ) { - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); bool done; tail_td->next_dtd_pointer = new_td; do { - if( usb_endpoint_is_in(endpoint->address) ) { - if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number) ) - return; - } else { - if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number) ) - return; + if (usb_endpoint_is_priming(endpoint)) { + return; } USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; @@ -237,18 +243,6 @@ void usb_endpoint_schedule_append( } } -/* -static bool usb_endpoint_is_priming( - const usb_endpoint_t* const endpoint -) { - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if( usb_endpoint_is_in(endpoint->address) ) { - return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number); - } else { - return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number); - } -} -*/ void usb_endpoint_flush( const usb_endpoint_t* const endpoint ) { From a88b2ad349429879205e0c47df21392911efea58 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:40:53 -0400 Subject: [PATCH 15/48] usb_queue: Transfer needs to be added to queue in both paths --- firmware/hackrf_usb/usb_queue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 0aa3a3c3..c0b5f7d7 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -139,13 +139,13 @@ void usb_transfer_schedule( fill_in_transfer(transfer, data, maximum_length); transfer->completion_cb = completion_cb; // TODO: disable_interrupts(); + endpoint_add_transfer(endpoint, transfer); usb_transfer_t* tail = endpoint_transfers[index]; if (tail == NULL) { usb_endpoint_schedule_wait(endpoint, &transfer->td); } else { - for (; tail->next != NULL; tail = tail->next); - endpoint_add_transfer(endpoint, transfer); - usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); + for (; tail->next != NULL; tail = tail->next); + usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); } //enable_interrupts(); } From 0d1ea071515eda1ff97fd0d21542fe4f7a606f29 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:41:39 -0400 Subject: [PATCH 16/48] usb: Check is_priming before loop --- firmware/hackrf_usb/usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 09e3d127..5a151aec 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -228,11 +228,11 @@ void usb_endpoint_schedule_append( tail_td->next_dtd_pointer = new_td; - do { - if (usb_endpoint_is_priming(endpoint)) { - return; - } + if (usb_endpoint_is_priming(endpoint)) { + return; + } + do { USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; done = usb_endpoint_is_ready(endpoint); } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW)); From eef6a0f0566e13289d08a8d7654316771c20fc06 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:51:18 -0400 Subject: [PATCH 17/48] usb_queue: Assert that transaction succeeded --- firmware/hackrf_usb/usb_queue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index c0b5f7d7..10fd1ef8 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -160,6 +160,13 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) { usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); unsigned int transferred = transfer->maximum_length - transfer->td.total_bytes; + uint8_t status = transfer->td.total_bytes; + if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE + || status & USB_TD_DTD_TOKEN_STATUS_HALTED + || status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR + || status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) { + assert(0); + } if (transfer->completion_cb) transfer->completion_cb(transfer, transferred); free_transfer(transfer); From f36943df627acf58e00d0698c348a93b0e417043 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 16:51:48 -0400 Subject: [PATCH 18/48] usb: Whitespace cleanup --- firmware/hackrf_usb/usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 5a151aec..a44d9164 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -90,25 +90,25 @@ static void usb_clear_all_pending_interrupts() { static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) { // Wait until controller has parsed new transfer descriptors and prepared // receive buffers. - while( USB0_ENDPTPRIME & mask ); + while( USB0_ENDPTPRIME & mask ); } static void usb_flush_endpoints(const uint32_t mask) { // Clear any primed buffers. If a packet is in progress, that transfer // will continue until completion. - USB0_ENDPTFLUSH = mask; + USB0_ENDPTFLUSH = mask; } static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) { // Wait until controller has flushed all endpoints / cleared any primed // buffers. - while( USB0_ENDPTFLUSH & mask ); + while( USB0_ENDPTFLUSH & mask ); } static void usb_flush_primed_endpoints(const uint32_t mask) { - usb_wait_for_endpoint_priming_to_finish(mask); + usb_wait_for_endpoint_priming_to_finish(mask); usb_flush_endpoints(mask); - usb_wait_for_endpoint_flushing_to_finish(mask); + usb_wait_for_endpoint_flushing_to_finish(mask); } static void usb_flush_all_primed_endpoints() { From f3a36d06fd4befd0b8e99d96df30f697ce9a18ec Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 17:11:29 -0400 Subject: [PATCH 19/48] usb_queue: Add new transfer after finding tail --- firmware/hackrf_usb/usb_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 10fd1ef8..4dcd57c6 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -139,8 +139,8 @@ void usb_transfer_schedule( fill_in_transfer(transfer, data, maximum_length); transfer->completion_cb = completion_cb; // TODO: disable_interrupts(); - endpoint_add_transfer(endpoint, transfer); usb_transfer_t* tail = endpoint_transfers[index]; + endpoint_add_transfer(endpoint, transfer); if (tail == NULL) { usb_endpoint_schedule_wait(endpoint, &transfer->td); } else { From 2ad4cbe087eed22840015c708e8380b8584060d4 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 17:48:43 -0400 Subject: [PATCH 20/48] usb_queue: Fix calculation of transferred --- firmware/hackrf_usb/usb_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 4dcd57c6..853ace75 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -159,7 +159,8 @@ void usb_transfer_schedule_ack( void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) { usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); - unsigned int transferred = transfer->maximum_length - transfer->td.total_bytes; + unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; + unsigned int transferred = transfer->maximum_length - total_bytes; uint8_t status = transfer->td.total_bytes; if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE || status & USB_TD_DTD_TOKEN_STATUS_HALTED From 1d9119fd8acf2b0c12501620dd2d826e9acb7867 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 17:48:55 -0400 Subject: [PATCH 21/48] usb: Ensure TERMINATE bit gets set --- firmware/hackrf_usb/usb.c | 3 ++- firmware/hackrf_usb/usb_queue.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index a44d9164..472e5eb5 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -218,7 +218,8 @@ void usb_endpoint_schedule_wait( // Schedule an already filled-in transfer descriptor for execution on // the given endpoint, appending to the end of the endpoint's queue if // there are pending TDs. Note that this requires that one knows the -// tail of the endpoint's TD queue +// tail of the endpoint's TD queue. Moreover, the user is responsible +// for setting the TERMINATE bit of next_dtd_pointer if needed. void usb_endpoint_schedule_append( const usb_endpoint_t* const endpoint, usb_transfer_descriptor_t* const tail_td, diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 853ace75..dc8ec2eb 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -137,6 +137,7 @@ void usb_transfer_schedule( usb_transfer_t* const transfer = allocate_transfer(); uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); fill_in_transfer(transfer, data, maximum_length); + transfer->td.next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; transfer->completion_cb = completion_cb; // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; From 28fcb2a961dd2bdfcd114d8d01f4abc38a8a98d3 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 17:51:42 -0400 Subject: [PATCH 22/48] usb_queue: Merge fill_in_transfer into schedule --- firmware/hackrf_usb/usb_queue.c | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index dc8ec2eb..64822840 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -54,28 +54,6 @@ void usb_queue_init() { } t->next = NULL; } - -static void fill_in_transfer(usb_transfer_t* transfer, - void* const data, - const uint32_t maximum_length -) { - usb_transfer_descriptor_t* const td = &transfer->td; - - // Configure the transfer. descriptor - td->total_bytes = - USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) - | USB_TD_DTD_TOKEN_IOC - | USB_TD_DTD_TOKEN_MULTO(0) - | USB_TD_DTD_TOKEN_STATUS_ACTIVE - ; - td->buffer_pointer_page[0] = (uint32_t)data; - td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; - td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; - td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; - td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; - - transfer->maximum_length = maximum_length; -} /* Allocate a transfer */ static usb_transfer_t* allocate_transfer() @@ -135,16 +113,36 @@ void usb_transfer_schedule( const transfer_completion_cb completion_cb ) { usb_transfer_t* const transfer = allocate_transfer(); + assert(transfer != NULL); + usb_transfer_descriptor_t* const td = &transfer->td; uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); - fill_in_transfer(transfer, data, maximum_length); + + // Configure the transfer descriptor + td->total_bytes = + USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) + | USB_TD_DTD_TOKEN_IOC + | USB_TD_DTD_TOKEN_MULTO(0) + | USB_TD_DTD_TOKEN_STATUS_ACTIVE + ; + td->buffer_pointer_page[0] = (uint32_t)data; + td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000; + td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000; + td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000; + td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000; + + // Fill in transfer fields + transfer->maximum_length = maximum_length; transfer->td.next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; transfer->completion_cb = completion_cb; + // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; endpoint_add_transfer(endpoint, transfer); if (tail == NULL) { + // The queue is currently empty, we need to re-prime usb_endpoint_schedule_wait(endpoint, &transfer->td); } else { + // The queue is currently running, try to append for (; tail->next != NULL; tail = tail->next); usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); } From 13589b86958143757eeed128b61118b20937f8f7 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 18:14:15 -0400 Subject: [PATCH 23/48] usb_queue: Ensure fields get set --- firmware/hackrf_usb/usb_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 64822840..7c7fa6f9 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -118,6 +118,7 @@ void usb_transfer_schedule( uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); // Configure the transfer descriptor + td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; td->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) | USB_TD_DTD_TOKEN_IOC @@ -132,8 +133,8 @@ void usb_transfer_schedule( // Fill in transfer fields transfer->maximum_length = maximum_length; - transfer->td.next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; transfer->completion_cb = completion_cb; + transfer->endpoint = endpoint; // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; From f1fc4a6d73d40034b2bb457fc3a191be28b0ecb5 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 3 Jul 2013 19:11:26 -0400 Subject: [PATCH 24/48] usb_queue: Account for completion of multiple transfers --- firmware/hackrf_usb/usb_queue.c | 58 ++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 7c7fa6f9..1768b0a5 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -93,19 +93,6 @@ static void endpoint_add_transfer( //enable_irqs(); } -/* Pop off the transfer at the top of an endpoint's queue */ -static usb_transfer_t* endpoint_pop_transfer( - const usb_endpoint_t* const endpoint -) { - uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); - //FIXME disable_irqs(); - usb_transfer_t* transfer = endpoint_transfers[index]; - assert(transfer != NULL); - endpoint_transfers[index] = transfer->next; - //enable_irqs(); - return transfer; -} - void usb_transfer_schedule( const usb_endpoint_t* const endpoint, void* const data, @@ -134,12 +121,12 @@ void usb_transfer_schedule( // Fill in transfer fields transfer->maximum_length = maximum_length; transfer->completion_cb = completion_cb; - transfer->endpoint = endpoint; + transfer->endpoint = (usb_endpoint_t*) endpoint; // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; endpoint_add_transfer(endpoint, transfer); - if (tail == NULL) { + if (1 || tail == NULL) { // The queue is currently empty, we need to re-prime usb_endpoint_schedule_wait(endpoint, &transfer->td); } else { @@ -156,19 +143,36 @@ void usb_transfer_schedule_ack( usb_transfer_schedule(endpoint, 0, 0, NULL); } +/* Called when an endpoint might have completed a transfer */ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) { - usb_transfer_t* transfer = endpoint_pop_transfer(endpoint); - unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; - unsigned int transferred = transfer->maximum_length - total_bytes; - uint8_t status = transfer->td.total_bytes; - if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE - || status & USB_TD_DTD_TOKEN_STATUS_HALTED - || status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR - || status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) { - assert(0); + uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); + usb_transfer_t* transfer = endpoint_transfers[index]; + + while (transfer != NULL) { + uint8_t status = transfer->td.total_bytes; + + // Check for failures + if ( status & USB_TD_DTD_TOKEN_STATUS_HALTED + || status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR + || status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) { + assert(0); + } + + // Still not finished + if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE) + break; + + // Invoke completion callback + unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; + unsigned int transferred = transfer->maximum_length - total_bytes; + if (transfer->completion_cb) + transfer->completion_cb(transfer, transferred); + + // Advance head and free + endpoint_transfers[index] = transfer->next; + usb_transfer_t* next = transfer->next; + free_transfer(transfer); + transfer = next; } - if (transfer->completion_cb) - transfer->completion_cb(transfer, transferred); - free_transfer(transfer); } From 63ce57b30632e0bbd92c8b74257806b0807bb9ba Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 11:26:22 -0400 Subject: [PATCH 25/48] usb_queue: Clarify comment --- firmware/hackrf_usb/usb_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 1768b0a5..27053c35 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -169,7 +169,7 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) if (transfer->completion_cb) transfer->completion_cb(transfer, transferred); - // Advance head and free + // Advance head and free transfer endpoint_transfers[index] = transfer->next; usb_transfer_t* next = transfer->next; free_transfer(transfer); From b6f9a3699a544ca505c5bccb335733b90bb41ee9 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 11:35:32 -0400 Subject: [PATCH 26/48] usb_queue: Kill assert reference --- firmware/hackrf_usb/usb_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 27053c35..ea9e6e69 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -156,7 +156,8 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) if ( status & USB_TD_DTD_TOKEN_STATUS_HALTED || status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR || status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) { - assert(0); + // TODO: Uh oh, do something useful here + while (1); } // Still not finished From df97b6584bbd50c5bd225dea51618ff738953888 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 11:53:09 -0400 Subject: [PATCH 27/48] hackrf_usb: Port to usb_queue --- firmware/hackrf_usb/hackrf_usb.c | 65 +++++--------------------------- 1 file changed, 10 insertions(+), 55 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 14d1722b..acfe0c53 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -50,9 +50,6 @@ uint8_t* const usb_bulk_buffer = (uint8_t*)0x20004000; static volatile uint32_t usb_bulk_buffer_offset = 0; static const uint32_t usb_bulk_buffer_mask = 32768 - 1; -usb_transfer_descriptor_t usb_td_bulk[2] ATTR_ALIGNED(64); -const uint_fast8_t usb_td_bulk_count = sizeof(usb_td_bulk) / sizeof(usb_td_bulk[0]); - /* TODO remove this big buffer and use streaming for CPLD */ #define CPLD_XSVF_MAX_LEN (65536) uint8_t cpld_xsvf_buffer[CPLD_XSVF_MAX_LEN]; @@ -182,50 +179,6 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) return success; } -static void usb_init_buffers_bulk() { - usb_td_bulk[0].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - usb_td_bulk[0].total_bytes - = USB_TD_DTD_TOKEN_TOTAL_BYTES(16384) - | USB_TD_DTD_TOKEN_MULTO(0) - ; - usb_td_bulk[0].buffer_pointer_page[0] = (uint32_t)&usb_bulk_buffer[0x0000]; - usb_td_bulk[0].buffer_pointer_page[1] = (uint32_t)&usb_bulk_buffer[0x1000]; - usb_td_bulk[0].buffer_pointer_page[2] = (uint32_t)&usb_bulk_buffer[0x2000]; - usb_td_bulk[0].buffer_pointer_page[3] = (uint32_t)&usb_bulk_buffer[0x3000]; - usb_td_bulk[0].buffer_pointer_page[4] = (uint32_t)&usb_bulk_buffer[0x4000]; - - usb_td_bulk[1].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - usb_td_bulk[1].total_bytes - = USB_TD_DTD_TOKEN_TOTAL_BYTES(16384) - | USB_TD_DTD_TOKEN_MULTO(0) - ; - usb_td_bulk[1].buffer_pointer_page[0] = (uint32_t)&usb_bulk_buffer[0x4000]; - usb_td_bulk[1].buffer_pointer_page[1] = (uint32_t)&usb_bulk_buffer[0x5000]; - usb_td_bulk[1].buffer_pointer_page[2] = (uint32_t)&usb_bulk_buffer[0x6000]; - usb_td_bulk[1].buffer_pointer_page[3] = (uint32_t)&usb_bulk_buffer[0x7000]; - usb_td_bulk[1].buffer_pointer_page[4] = (uint32_t)&usb_bulk_buffer[0x8000]; -} - -void usb_endpoint_schedule_no_int( - const usb_endpoint_t* const endpoint, - usb_transfer_descriptor_t* const td -) { - // Ensure that endpoint is ready to be primed. - // It may have been flushed due to an aborted transaction. - // TODO: This should be preceded by a flush? - while( usb_endpoint_is_ready(endpoint) ); - - // Configure a transfer. - td->total_bytes = - USB_TD_DTD_TOKEN_TOTAL_BYTES(16384) - /*| USB_TD_DTD_TOKEN_IOC*/ - | USB_TD_DTD_TOKEN_MULTO(0) - | USB_TD_DTD_TOKEN_STATUS_ACTIVE - ; - - usb_endpoint_prime(endpoint, td); -} - usb_configuration_t usb_configuration_high_speed = { .number = 1, .speed = USB_SPEED_HIGH, @@ -281,7 +234,7 @@ usb_endpoint_t usb_endpoint_bulk_in = { .in = &usb_endpoint_bulk_in, .out = 0, .setup_complete = 0, - .transfer_complete = 0, + .transfer_complete = usb_queue_transfer_complete }; usb_endpoint_t usb_endpoint_bulk_out = { @@ -290,7 +243,7 @@ usb_endpoint_t usb_endpoint_bulk_out = { .in = 0, .out = &usb_endpoint_bulk_out, .setup_complete = 0, - .transfer_complete = 0, + .transfer_complete = usb_queue_transfer_complete }; void baseband_streaming_disable() { @@ -307,8 +260,6 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { transceiver_mode = new_transceiver_mode; - usb_init_buffers_bulk(); - if( transceiver_mode == TRANSCEIVER_MODE_RX ) { gpio_clear(PORT_LED1_3, PIN_LED3); gpio_set(PORT_LED1_3, PIN_LED2); @@ -997,20 +948,24 @@ int main(void) { while( usb_bulk_buffer_offset < 16384 ); // Set up IN transfer of buffer 0. - usb_endpoint_schedule_no_int( + usb_transfer_schedule( (transceiver_mode == TRANSCEIVER_MODE_RX) ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, - &usb_td_bulk[0] + &usb_bulk_buffer[0x0000], + 0x4000, + NULL ); // Wait until buffer 1 is transmitted/received. while( usb_bulk_buffer_offset >= 16384 ); // Set up IN transfer of buffer 1. - usb_endpoint_schedule_no_int( + usb_transfer_schedule( (transceiver_mode == TRANSCEIVER_MODE_RX) ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, - &usb_td_bulk[1] + &usb_bulk_buffer[0x4000], + 0x4000, + NULL ); } From dd81921650fab8bd5c4da28925a5f3ad3049e774 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 13:36:25 -0400 Subject: [PATCH 28/48] usb_queue: Reduce transfer_pool size --- firmware/hackrf_usb/usb_queue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index ea9e6e69..b68d3fc5 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -36,7 +36,8 @@ struct _usb_transfer_t { transfer_completion_cb completion_cb; }; -usb_transfer_t transfer_pool[16]; +usb_transfer_t transfer_pool[8]; +const unsigned int transfer_pool_size = sizeof(transfer_pool) / sizeof(usb_transfer_t); // Available transfer list usb_transfer_t* free_transfers; @@ -49,7 +50,7 @@ usb_transfer_t* endpoint_transfers[12] = {}; void usb_queue_init() { usb_transfer_t* t = &transfer_pool[0]; free_transfers = t; - for (unsigned int i=0; i < sizeof(transfer_pool) / sizeof(usb_transfer_t) - 1; i++, t++) { + for (unsigned int i=0; i < transfer_pool_size - 1; i++, t++) { t->next = t+1; } t->next = NULL; From abb0b3f928c70c9b4f8f107e0db661f7e734ba30 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 14:01:32 -0400 Subject: [PATCH 29/48] hackrf_usb: Forgotten initialization --- firmware/hackrf_usb/hackrf_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index acfe0c53..5ece18a6 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -918,6 +918,8 @@ int main(void) { enable_1v8_power(); cpu_clock_init(); + usb_queue_init(); + usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); usb_device_init(0, &usb_device); From 3e3a57e3ced46b6663ef97093d3d425509d50fbf Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 15:30:15 -0400 Subject: [PATCH 30/48] hackrf_usb: Don't attempt to schedule transfers when OFF The endpoints are disabled so no good will come of this --- firmware/hackrf_usb/hackrf_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 5ece18a6..348b9236 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -946,6 +946,9 @@ int main(void) { #endif while(true) { + if (transceiver_mode == TRANSCEIVER_MODE_OFF) + continue; + // Wait until buffer 0 is transmitted/received. while( usb_bulk_buffer_offset < 16384 ); From 5a70772295bb670215dd4d36fdf3e5985af99f71 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 4 Jul 2013 15:30:43 -0400 Subject: [PATCH 31/48] usb_queue: Enable transfer chaining Unfortunately this seems to be slightly broken. While hackrf_transfer streams fine, things fall apart when disabling streaming. Not sure why yet. --- firmware/hackrf_usb/usb_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index b68d3fc5..7492eb92 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -127,7 +127,7 @@ void usb_transfer_schedule( // TODO: disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; endpoint_add_transfer(endpoint, transfer); - if (1 || tail == NULL) { + if (tail == NULL) { // The queue is currently empty, we need to re-prime usb_endpoint_schedule_wait(endpoint, &transfer->td); } else { From 969647dbef657f254724cc185a956a6ca695a457 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Fri, 5 Jul 2013 11:15:23 -0400 Subject: [PATCH 32/48] usb_queue: Update queue before calling completion callback --- firmware/hackrf_usb/usb_queue.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 7492eb92..79e00095 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -165,6 +165,11 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE) break; + // Advance the head. We need to do this before invoking the completion + // callback as it might attempt to schedule a new transfer + endpoint_transfers[index] = transfer->next; + usb_transfer_t* next = transfer->next; + // Invoke completion callback unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; unsigned int transferred = transfer->maximum_length - total_bytes; @@ -172,8 +177,6 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) transfer->completion_cb(transfer, transferred); // Advance head and free transfer - endpoint_transfers[index] = transfer->next; - usb_transfer_t* next = transfer->next; free_transfer(transfer); transfer = next; } From 8fdc22f8c8605fe576327b6ac61f0804fe18ee20 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 17:00:23 -0400 Subject: [PATCH 33/48] usb-queue: Add flush utility --- firmware/hackrf_usb/usb_queue.c | 13 ++++++++++++- firmware/hackrf_usb/usb_queue.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 79e00095..b595b4e7 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -55,7 +55,7 @@ void usb_queue_init() { } t->next = NULL; } - + /* Allocate a transfer */ static usb_transfer_t* allocate_transfer() { @@ -93,6 +93,17 @@ static void endpoint_add_transfer( } //enable_irqs(); } + +void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint) +{ + uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); + //FIXME disable_irqs(); + while (endpoint_transfers[index]) { + usb_transfer_t * transfer = endpoint_transfers[index]; + endpoint_transfers[index] = transfer->next; + free_transfer(transfer); + } +} void usb_transfer_schedule( const usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index f6dc0203..90d59567 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -31,6 +31,8 @@ typedef struct _usb_transfer_t usb_transfer_t; typedef void (*transfer_completion_cb)(usb_transfer_t*, unsigned int); +void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint); + void usb_endpoint_schedule( const usb_endpoint_t* const endpoint, void* const data, From f12defebc65953a0d2c6860d8deeaf217681a323 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 17:08:51 -0400 Subject: [PATCH 34/48] usb: Ensure endpoint queue is flushed on disable/init --- firmware/hackrf_usb/usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 472e5eb5..8a02eb0e 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -24,6 +24,7 @@ #include "usb.h" #include "usb_type.h" +#include "usb_queue.h" #include "usb_standard_request.h" #include @@ -163,6 +164,7 @@ void usb_endpoint_disable( } else { USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE); } + usb_queue_flush_endpoint(endpoint); usb_endpoint_clear_pending_interrupts(endpoint); usb_endpoint_flush(endpoint); } @@ -248,6 +250,7 @@ void usb_endpoint_flush( const usb_endpoint_t* const endpoint ) { const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + usb_queue_flush_endpoint(endpoint); if( usb_endpoint_is_in(endpoint->address) ) { usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number)); } else { From 9f2dca3e4e2c2aa042f6b94cc1fe308bc1e22bc0 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 17:01:12 -0400 Subject: [PATCH 35/48] usb_standard_request: Always call configuration_changed_cb For reasons I don't entirely understand, bulk requests are suddenly ignored after a SET_CONFIGURATION request (even if the configuration did not change) unless the endpoints are reinitialized. This is done by configuration_changed_cb, therefore we call it for every request. --- firmware/hackrf_usb/usb_standard_request.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index 43f2379f..43c23ada 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -100,9 +100,11 @@ bool usb_set_configuration( if( new_configuration != device->configuration ) { // Configuration changed. device->configuration = new_configuration; - if (usb_configuration_changed_cb) - usb_configuration_changed_cb(device); } + + if (usb_configuration_changed_cb) + usb_configuration_changed_cb(device); + return true; } From 14526cd1c278f7ee6709ad19cefa1ff937bbf5d5 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 19:15:17 -0400 Subject: [PATCH 36/48] hackrf_usb: Be more careful in transceiver_mode check --- firmware/hackrf_usb/hackrf_usb.c | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 348b9236..b04fb9ae 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -946,32 +946,33 @@ int main(void) { #endif while(true) { - if (transceiver_mode == TRANSCEIVER_MODE_OFF) - continue; - // Wait until buffer 0 is transmitted/received. while( usb_bulk_buffer_offset < 16384 ); // Set up IN transfer of buffer 0. - usb_transfer_schedule( - (transceiver_mode == TRANSCEIVER_MODE_RX) - ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, - &usb_bulk_buffer[0x0000], - 0x4000, - NULL - ); + if (transceiver_mode != TRANSCEIVER_MODE_OFF) { + usb_transfer_schedule( + (transceiver_mode == TRANSCEIVER_MODE_RX) + ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, + &usb_bulk_buffer[0x0000], + 0x4000, + NULL + ); + } // Wait until buffer 1 is transmitted/received. while( usb_bulk_buffer_offset >= 16384 ); // Set up IN transfer of buffer 1. - usb_transfer_schedule( - (transceiver_mode == TRANSCEIVER_MODE_RX) - ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, - &usb_bulk_buffer[0x4000], - 0x4000, - NULL - ); + if (transceiver_mode != TRANSCEIVER_MODE_OFF) { + usb_transfer_schedule( + (transceiver_mode == TRANSCEIVER_MODE_RX) + ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, + &usb_bulk_buffer[0x4000], + 0x4000, + NULL + ); + } } return 0; From 36cf222ef498258d1c0f81d63f66d3c810b255c3 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 19:17:38 -0400 Subject: [PATCH 37/48] usb_queue: Add some interrupt disabling around critical sections --- firmware/hackrf_usb/usb_queue.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index b595b4e7..cb90959a 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -25,6 +25,8 @@ #include #include +#include + #include "usb.h" #include "usb_queue.h" @@ -60,20 +62,16 @@ void usb_queue_init() { static usb_transfer_t* allocate_transfer() { while (free_transfers == NULL); - //disable_irqs(); // FIXME usb_transfer_t* const transfer = free_transfers; free_transfers = transfer->next; - //enable_irqs(); return transfer; } /* Place a transfer in the free list */ static void free_transfer(usb_transfer_t* const transfer) { - //disable_irqs(); // FIXME transfer->next = free_transfers; free_transfers = transfer; - //enable_irqs(); } /* Add a transfer to the end of an endpoint's queue */ @@ -82,7 +80,6 @@ static void endpoint_add_transfer( usb_transfer_t* const transfer ) { uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); - //FIXME disable_irqs(); transfer->next = NULL; if (endpoint_transfers[index] != NULL) { usb_transfer_t* t = endpoint_transfers[index]; @@ -91,18 +88,18 @@ static void endpoint_add_transfer( } else { endpoint_transfers[index] = transfer; } - //enable_irqs(); } void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint) { uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); - //FIXME disable_irqs(); + cc_disable_interrupts(); while (endpoint_transfers[index]) { usb_transfer_t * transfer = endpoint_transfers[index]; endpoint_transfers[index] = transfer->next; free_transfer(transfer); } + cc_enable_interrupts(); } void usb_transfer_schedule( @@ -135,7 +132,7 @@ void usb_transfer_schedule( transfer->completion_cb = completion_cb; transfer->endpoint = (usb_endpoint_t*) endpoint; - // TODO: disable_interrupts(); + cc_disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; endpoint_add_transfer(endpoint, transfer); if (tail == NULL) { @@ -146,7 +143,7 @@ void usb_transfer_schedule( for (; tail->next != NULL; tail = tail->next); usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); } - //enable_interrupts(); + cc_enable_interrupts(); } void usb_transfer_schedule_ack( From d30d7309d9c09f6862239322d970033e3c07a352 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 19:17:57 -0400 Subject: [PATCH 38/48] usb_queue: Mark queues as volatile --- firmware/hackrf_usb/usb_queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index cb90959a..8253e0b6 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -42,12 +42,12 @@ usb_transfer_t transfer_pool[8]; const unsigned int transfer_pool_size = sizeof(transfer_pool) / sizeof(usb_transfer_t); // Available transfer list -usb_transfer_t* free_transfers; +usb_transfer_t* volatile free_transfers; #define USB_ENDPOINT_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) // Pending transfer heads -usb_transfer_t* endpoint_transfers[12] = {}; +usb_transfer_t* volatile endpoint_transfers[12] = {}; void usb_queue_init() { usb_transfer_t* t = &transfer_pool[0]; From a9f8103fec7c6a58472465b7147fe340517a489b Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 6 Jul 2013 19:21:12 -0400 Subject: [PATCH 39/48] hackrf_stop_rx: First set mode, then kill transfer thread Killing the transfer thread first means that the host stops polling the device for reads, causing the device to hang while scheduling the dTD --- host/libhackrf/src/hackrf.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 7e36dc55..f03f19aa 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -1141,14 +1141,13 @@ int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn cal int ADDCALL hackrf_stop_rx(hackrf_device* device) { - int result1, result2; - result1 = kill_transfer_thread(device); - result2 = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_OFF); - if (result2 != HACKRF_SUCCESS) + int result; + result = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_OFF); + if (result != HACKRF_SUCCESS) { return result2; } - return result1; + return kill_transfer_thread(device); } int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* tx_ctx) From df400eced6568a783456187356d3bfd9cfd48ec6 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 21:08:57 -0400 Subject: [PATCH 40/48] Bump libopencm3 --- firmware/libopencm3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libopencm3 b/firmware/libopencm3 index 87690732..e0040d7c 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit 87690732661dd049657967d3951cb8f4674ede00 +Subproject commit e0040d7c82d174c3ef1c4d3e860aa2ab765a9ab7 From cce17c42fd16ed7cf74c9653ddaf06cd7fafd61c Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 21:24:13 -0400 Subject: [PATCH 41/48] libopencm3: Update --- firmware/hackrf_usb/usb_queue.c | 8 ++++---- firmware/libopencm3 | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 8253e0b6..0341150a 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -93,13 +93,13 @@ static void endpoint_add_transfer( void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint) { uint_fast8_t index = USB_ENDPOINT_INDEX(endpoint->address); - cc_disable_interrupts(); + cm_disable_interrupts(); while (endpoint_transfers[index]) { usb_transfer_t * transfer = endpoint_transfers[index]; endpoint_transfers[index] = transfer->next; free_transfer(transfer); } - cc_enable_interrupts(); + cm_enable_interrupts(); } void usb_transfer_schedule( @@ -132,7 +132,7 @@ void usb_transfer_schedule( transfer->completion_cb = completion_cb; transfer->endpoint = (usb_endpoint_t*) endpoint; - cc_disable_interrupts(); + cm_disable_interrupts(); usb_transfer_t* tail = endpoint_transfers[index]; endpoint_add_transfer(endpoint, transfer); if (tail == NULL) { @@ -143,7 +143,7 @@ void usb_transfer_schedule( for (; tail->next != NULL; tail = tail->next); usb_endpoint_schedule_append(endpoint, &tail->td, &transfer->td); } - cc_enable_interrupts(); + cm_enable_interrupts(); } void usb_transfer_schedule_ack( diff --git a/firmware/libopencm3 b/firmware/libopencm3 index e0040d7c..0aabbbe3 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit e0040d7c82d174c3ef1c4d3e860aa2ab765a9ab7 +Subproject commit 0aabbbe366565d25f7cd817b57b2f2eab7f1911c From e23cc9bd6c5434f36dd7a3de7437c7316e97f265 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 21:25:31 -0400 Subject: [PATCH 42/48] usb_queue: Disable interrupts when allocating transfer --- firmware/hackrf_usb/usb_queue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 0341150a..ea6c2980 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -62,8 +62,10 @@ void usb_queue_init() { static usb_transfer_t* allocate_transfer() { while (free_transfers == NULL); + cm_disable_interrupts(); usb_transfer_t* const transfer = free_transfers; free_transfers = transfer->next; + cm_enable_interrupts(); return transfer; } From f50253eaa38ae33bf4dbda5050a22f48660a58f8 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 21:54:25 -0400 Subject: [PATCH 43/48] usb_queue: Use ldrex/strex to avoid disabling interrupts --- firmware/hackrf_usb/usb_queue.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index ea6c2980..683b3b96 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -26,6 +26,7 @@ #include #include +#include #include "usb.h" #include "usb_queue.h" @@ -61,19 +62,25 @@ void usb_queue_init() { /* Allocate a transfer */ static usb_transfer_t* allocate_transfer() { + bool aborted; + usb_transfer_t* transfer; while (free_transfers == NULL); - cm_disable_interrupts(); - usb_transfer_t* const transfer = free_transfers; - free_transfers = transfer->next; - cm_enable_interrupts(); + do { + transfer = (void *) __ldrex((uint32_t *) &free_transfers); + aborted = __strex((uint32_t) transfer->next, (uint32_t *) &free_transfers); + } while (aborted); + transfer->next = NULL; return transfer; } /* Place a transfer in the free list */ static void free_transfer(usb_transfer_t* const transfer) { - transfer->next = free_transfers; - free_transfers = transfer; + bool aborted; + do { + transfer->next = (void *) __ldrex((uint32_t *) &free_transfers); + aborted = __strex((uint32_t) transfer, (uint32_t *) &free_transfers); + } while (aborted); } /* Add a transfer to the end of an endpoint's queue */ From bb69f655b11187b8cf61ac51ca37045c1b0017df Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 21:58:06 -0400 Subject: [PATCH 44/48] usb_queue: Use while instead of for --- firmware/hackrf_usb/usb_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_queue.c b/firmware/hackrf_usb/usb_queue.c index 683b3b96..afb6c7e8 100644 --- a/firmware/hackrf_usb/usb_queue.c +++ b/firmware/hackrf_usb/usb_queue.c @@ -92,7 +92,7 @@ static void endpoint_add_transfer( transfer->next = NULL; if (endpoint_transfers[index] != NULL) { usb_transfer_t* t = endpoint_transfers[index]; - for (; t->next != NULL; t = t->next); + while (t->next != NULL) t = t->next; t->next = transfer; } else { endpoint_transfers[index] = transfer; From b738cd52940090b58c642cf85223cb212185bcca Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 23:21:11 -0400 Subject: [PATCH 45/48] fix1 --- firmware/hackrf_usb/usb_standard_request.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index 43c23ada..9263a5bb 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -102,8 +102,8 @@ bool usb_set_configuration( device->configuration = new_configuration; } - if (usb_configuration_changed_cb) - usb_configuration_changed_cb(device); + if (usb_configuration_changed_cb) + usb_configuration_changed_cb(device); return true; } From f6b41dbda50cbe58f953a6213d9806600ac5f799 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 23:21:18 -0400 Subject: [PATCH 46/48] fix2 --- firmware/hackrf_usb/usb_standard_request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_standard_request.c b/firmware/hackrf_usb/usb_standard_request.c index 9263a5bb..98e50142 100644 --- a/firmware/hackrf_usb/usb_standard_request.c +++ b/firmware/hackrf_usb/usb_standard_request.c @@ -121,7 +121,7 @@ static usb_request_status_t usb_send_descriptor( endpoint->in, descriptor_data, (setup_length > descriptor_length) ? descriptor_length : setup_length, - NULL + NULL ); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; From 0e14a3840314a6f58739b0e4a32ea7c9ade58bd0 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sun, 7 Jul 2013 23:22:34 -0400 Subject: [PATCH 47/48] fix3 --- host/libhackrf/src/hackrf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index f03f19aa..3fd8051c 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -1141,7 +1141,7 @@ int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn cal int ADDCALL hackrf_stop_rx(hackrf_device* device) { - int result; + int result; result = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_OFF); if (result != HACKRF_SUCCESS) { From 3642fe9bc62033bfa5123c141854bcfe94d0f1e9 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Tue, 9 Jul 2013 20:57:37 -0400 Subject: [PATCH 48/48] usb_queue: Kill dead declaration --- firmware/hackrf_usb/usb_queue.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/firmware/hackrf_usb/usb_queue.h b/firmware/hackrf_usb/usb_queue.h index 90d59567..8c776d3e 100644 --- a/firmware/hackrf_usb/usb_queue.h +++ b/firmware/hackrf_usb/usb_queue.h @@ -33,12 +33,6 @@ typedef void (*transfer_completion_cb)(usb_transfer_t*, unsigned int); void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint); -void usb_endpoint_schedule( - const usb_endpoint_t* const endpoint, - void* const data, - const uint32_t maximum_length -); - void usb_transfer_schedule( const usb_endpoint_t* const endpoint, void* const data,