From: Keith Packard Date: Mon, 8 Jan 2018 01:43:42 +0000 (-0800) Subject: altos/stmf0: use double buffering for USB rx data X-Git-Tag: 1.8.5~1^2~2^2~11 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=8545ed42bd29152f4937fb6457aba5fbd57e7691 altos/stmf0: use double buffering for USB rx data This also allows us to stop shadowing USB rx buffers in system ram Signed-off-by: Keith Packard --- diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index 0963b64a..5b9af00b 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -106,12 +106,9 @@ static uint8_t ao_usb_tx_count; #endif #if AO_USB_HAS_OUT -static uint16_t ao_usb_out_rx_offset; -static uint16_t *ao_usb_out_rx_buffer; - -/* System ram shadow of USB buffer; writing individual bytes is - * too much of a pain (sigh) */ -static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint16_t ao_usb_out_rx_offset[2]; +static uint16_t *ao_usb_out_rx_buffer[2]; +static uint8_t ao_usb_out_rx_which; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; #endif @@ -211,10 +208,18 @@ static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { return (epr >> STM_USB_EPR_DTOG_RX) & 1; } +static inline uint32_t ao_usb_epr_sw_buf_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_SW_BUF_TX) & 1; +} + static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { return (epr >> STM_USB_EPR_DTOG_TX) & 1; } +static inline uint32_t ao_usb_epr_sw_buf_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_SW_BUF_RX) & 1; +} + /* * Set current device address and mark the * interface as active @@ -298,6 +303,14 @@ _ao_usb_set_stat_tx(int ep, uint32_t stat_tx) _tx_dbg1("set_stat_tx bottom", epr_write); } +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + ao_arch_block_interrupts(); + _ao_usb_set_stat_tx(ep, stat_tx); + ao_arch_release_interrupts(); +} + static void _ao_usb_toggle_dtog(int ep, uint32_t dtog_rx, uint32_t dtog_tx) { @@ -313,14 +326,6 @@ _ao_usb_toggle_dtog(int ep, uint32_t dtog_rx, uint32_t dtog_tx) _tx_dbg1("toggle_dtog bottom", epr_write); } -static void -ao_usb_set_stat_tx(int ep, uint32_t stat_tx) -{ - ao_arch_block_interrupts(); - _ao_usb_set_stat_tx(ep, stat_tx); - ao_arch_release_interrupts(); -} - static void _ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { uint16_t epr_write, epr_old; @@ -342,11 +347,14 @@ ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { } /* - * Set just endpoint 0, for use during startup + * Initialize an entpoint */ static void -ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx, uint32_t kind, uint32_t dtog_rx, uint32_t dtog_tx) +ao_usb_init_ep(uint8_t ep, uint16_t addr, uint16_t type, + uint16_t stat_rx, uint16_t stat_tx, + uint16_t kind, + uint16_t dtog_rx, uint16_t dtog_tx) { uint16_t epr; @@ -397,9 +405,14 @@ ao_usb_alloc_buffers(void) #if AO_USB_HAS_OUT sram_addr += (sram_addr & 1); - ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(sram_addr); - ao_usb_out_rx_offset = sram_addr; + ao_usb_out_rx_buffer[0] = ao_usb_packet_buffer_addr(sram_addr); + ao_usb_out_rx_offset[0] = sram_addr; + sram_addr += AO_USB_OUT_SIZE; + sram_addr += (sram_addr & 1); + ao_usb_out_rx_buffer[1] = ao_usb_packet_buffer_addr(sram_addr); + ao_usb_out_rx_offset[1] = sram_addr; sram_addr += AO_USB_OUT_SIZE; + ao_usb_out_rx_which = 1; #endif #if AO_USB_HAS_IN @@ -506,16 +519,21 @@ ao_usb_set_configuration(void) #if AO_USB_HAS_OUT /* Set up the OUT end point */ - ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset; - ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | - (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_bdt[AO_USB_OUT_EPR].double_rx[0].addr = ao_usb_out_rx_offset[0]; + ao_usb_bdt[AO_USB_OUT_EPR].double_rx[0].count = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_bdt[AO_USB_OUT_EPR].double_rx[1].addr = ao_usb_out_rx_offset[1]; + ao_usb_bdt[AO_USB_OUT_EPR].double_rx[1].count = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + + /* set 'our' buffer to one, and the device buffer to 0 */ ao_usb_init_ep(AO_USB_OUT_EPR, AO_USB_OUT_EP, STM_USB_EPR_EP_TYPE_BULK, STM_USB_EPR_STAT_RX_VALID, STM_USB_EPR_STAT_TX_DISABLED, - STM_USB_EPR_EP_KIND_SNGL_BUF, 0, 0); + STM_USB_EPR_EP_KIND_DBL_BUF, 0, 1); #endif #if AO_USB_HAS_IN @@ -606,14 +624,22 @@ ao_usb_copy_rx(uint8_t *dst, uint16_t *base, uint16_t bytes) *dst = *base; } -static uint8_t +static inline void ao_usb_tx_byte(uint16_t *base, uint8_t tx_count, char byte) { if (tx_count & 1) base[tx_count >> 1] |= ((uint16_t) byte) << 8; else base[tx_count >> 1] = (uint16_t) (uint8_t) byte; - return tx_count + 1; +} + +static inline char +ao_usb_rx_byte(uint16_t *base, uint8_t rx_count) +{ + if (rx_count & 1) + return (char) (base[rx_count>>1] >> 8); + else + return (char) base[rx_count>>1]; } /* Send an IN data packet */ @@ -1096,7 +1122,7 @@ ao_usb_putchar(char c) _ao_usb_in_wait(); ao_usb_in_flushed = 0; - ao_usb_tx_count = ao_usb_tx_byte(ao_usb_in_tx_buffer[ao_usb_in_tx_which], ao_usb_tx_count, c); + ao_usb_tx_byte(ao_usb_in_tx_buffer[ao_usb_in_tx_which], ao_usb_tx_count++, c); /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { @@ -1177,7 +1203,8 @@ ao_usb_putchar2(char c) _ao_usb_in2_wait(); ao_usb_in2_flushed = 0; - ao_usb_tx2_count = ao_usb_tx_byte(ao_usb_in2_tx_buffer[ao_usb_in2_tx_which], ao_usb_tx2_count, c); + ao_usb_tx_byte(ao_usb_in2_tx_buffer[ao_usb_in2_tx_which], ao_usb_tx2_count, c); + ao_usb_tx2_count++; /* Send the packet when full */ if (ao_usb_tx2_count == AO_USB_IN_SIZE) { @@ -1193,20 +1220,24 @@ ao_usb_putchar2(char c) static void _ao_usb_out_recv(void) { - _rx_dbg0("out_recv top"); + _rx_dbg1("out_recv top", stm_usb.epr[AO_USB_OUT_EPR].r); + + /* Clear packet available field until we get another interrupt */ ao_usb_out_avail = 0; - ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + /* Switch to new buffer */ + ao_usb_out_rx_which = 1 - ao_usb_out_rx_which; - _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_copy_rx(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); - debug_data("\n"); + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].double_rx[ao_usb_out_rx_which].count & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; ao_usb_rx_pos = 0; - /* ACK the packet */ - _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); + /* Toggle the SW_BUF_RX bit */ + _ao_usb_toggle_dtog(AO_USB_OUT_EPR, 0, 1); + +// /* Ack the packet */ +// _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); + + _rx_dbg1("out_recv count", ao_usb_rx_count); } int @@ -1221,17 +1252,18 @@ _ao_usb_pollchar(void) if (ao_usb_rx_pos != ao_usb_rx_count) break; - _rx_dbg0("poll check"); +// _rx_dbg0("poll check"); /* Check to see if a packet has arrived */ if (!ao_usb_out_avail) { - _rx_dbg0("poll none"); +// _rx_dbg0("poll none"); return AO_READ_AGAIN; } _ao_usb_out_recv(); } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + c = ao_usb_rx_byte(ao_usb_out_rx_buffer[ao_usb_out_rx_which], ao_usb_rx_pos++); + _rx_dbg1("char", c); return c; } @@ -1510,8 +1542,8 @@ struct ao_usb_dbg { #define NUM_USB_DBG 128 -static struct ao_usb_dbg dbg[128]; -static int dbg_i; +struct ao_usb_dbg dbg[128]; +int dbg_i; static void _dbg(int line, char *msg, uint32_t value) { @@ -1532,7 +1564,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].rx_count = ao_usb_rx_count; dbg[dbg_i].rx_pos = ao_usb_rx_pos; dbg[dbg_i].out_avail = ao_usb_out_avail; - dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR]; + dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR].r; #endif if (++dbg_i == NUM_USB_DBG) dbg_i = 0; diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 1dbe6a12..277fa223 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -1890,6 +1890,7 @@ extern struct stm_usb stm_usb; #define STM_USB_EPR_CTR_RX 15 #define STM_USB_EPR_CTR_RX_WRITE_INVARIANT 1 #define STM_USB_EPR_DTOG_RX 14 +#define STM_USB_EPR_SW_BUF_TX 14 #define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT 0 #define STM_USB_EPR_STAT_RX 12 #define STM_USB_EPR_STAT_RX_DISABLED 0 @@ -1913,6 +1914,7 @@ extern struct stm_usb stm_usb; #define STM_USB_EPR_CTR_TX 7 #define STM_USB_CTR_TX_WRITE_INVARIANT 1 #define STM_USB_EPR_DTOG_TX 6 +#define STM_USB_EPR_SW_BUF_RX 6 #define STM_USB_EPR_DTOG_TX_WRITE_INVARIANT 0 #define STM_USB_EPR_STAT_TX 4 #define STM_USB_EPR_STAT_TX_DISABLED 0