From: Keith Packard Date: Tue, 27 Jan 2015 06:12:40 +0000 (-0800) Subject: altos/stmf0: Add faster USB path X-Git-Tag: 1.6~60 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=a01effc2f64c757c907e0f4937b4d3710b97bde0 altos/stmf0: Add faster USB path This adds a way to allocate private USB buffers for sending data without needing to copy it again. It requires ensuring that all accesses are 16 bits aligned to 16 bit boundaries. Signed-off-by: Keith Packard --- diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index a5c6764b..3db96be2 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -384,4 +384,17 @@ static inline void ao_arch_start_scheduler(void) { ao_arch_irqrestore(__mask); \ } while (0) +/* ao_usb_stm.c */ + +#if AO_USB_DIRECTIO +uint16_t * +ao_usb_alloc(void); + +void +ao_usb_free(uint16_t *buffer); + +void +ao_usb_write(uint16_t *buffer, uint16_t len); +#endif /* AO_USB_DIRECTIO */ + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index b9d86368..e0ff541a 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -80,6 +80,7 @@ static uint16_t *ao_usb_ep0_tx_buffer; static uint16_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ +static uint16_t ao_usb_in_tx_offset; static uint16_t *ao_usb_in_tx_buffer; static uint16_t *ao_usb_out_rx_buffer; @@ -141,6 +142,13 @@ static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) return (uint16_t *) (stm_usb_sram + sram_addr); } +#if AO_USB_DIRECTIO +static inline uint16_t ao_usb_packet_buffer_offset(uint16_t *addr) +{ + return (uint16_t) ((uint8_t *) addr - stm_usb_sram); +} +#endif + static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK; } @@ -368,7 +376,6 @@ ao_usb_set_configuration(void) /* Set up the INT end point */ ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_INT_SIZE; ao_usb_init_ep(AO_USB_INT_EPR, @@ -393,7 +400,8 @@ ao_usb_set_configuration(void) /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_in_tx_offset = ao_usb_sram_addr; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_in_tx_offset); ao_usb_sram_addr += AO_USB_IN_SIZE; ao_usb_init_ep(AO_USB_IN_EPR, @@ -415,7 +423,7 @@ static uint16_t reset_count; */ static void -ao_usb_write(const uint8_t *src, uint16_t *base, uint16_t bytes) +ao_usb_copy_tx(const uint8_t *src, uint16_t *base, uint16_t bytes) { while (bytes >= 2) { *base++ = src[0] | (src[1] << 8); @@ -427,7 +435,7 @@ ao_usb_write(const uint8_t *src, uint16_t *base, uint16_t bytes) } static void -ao_usb_read(uint8_t *dst, uint16_t *base, uint16_t bytes) +ao_usb_copy_rx(uint8_t *dst, uint16_t *base, uint16_t bytes) { while (bytes >= 2) { uint16_t s = *base++; @@ -462,7 +470,7 @@ ao_usb_ep0_flush(void) ao_usb_ep0_in_len -= this_len; debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); + ao_usb_copy_tx(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); debug_data ("\n"); ao_usb_ep0_in_data += this_len; @@ -484,7 +492,7 @@ ao_usb_ep0_fill(void) /* Pull all of the data out of the packet */ debug_data ("Fill EP0 len %d:", len); - ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len); + ao_usb_copy_rx(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len); debug_data ("\n"); ao_usb_ep0_out_data += len; @@ -773,7 +781,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_copy_tx(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; ao_usb_tx_count = 0; _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); @@ -851,7 +860,7 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d:", ao_usb_rx_count); - ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); + ao_usb_copy_rx(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); debug_data("\n"); ao_usb_rx_pos = 0; @@ -897,6 +906,47 @@ ao_usb_getchar(void) return c; } +#if AO_USB_DIRECTIO +uint16_t * +ao_usb_alloc(void) +{ + uint16_t *buffer; + + if (!ao_usb_running) + return NULL; + buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + return buffer; +} + +void +ao_usb_free(uint16_t *addr) +{ + uint16_t offset = ao_usb_packet_buffer_offset(addr); + if (offset < ao_usb_sram_addr) + ao_usb_sram_addr = offset; +} + +void +ao_usb_write(uint16_t *buffer, uint16_t len) +{ + ao_arch_block_interrupts(); + + /* Flush any pending regular */ + if (ao_usb_tx_count) + _ao_usb_in_send(); + + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + ao_usb_in_flushed = (len != AO_USB_IN_SIZE); + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = len; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + ao_arch_release_interrupts(); +} +#endif + void ao_usb_disable(void) {