X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fstm%2Fao_usb_stm.c;h=7f81e20e67c01b948f9703659ffc3c1acf4b87ca;hp=e484cd22f03c58ae0e9cb319e91a6d0bcb5d91fe;hb=49ce3e9a2eb4e1918773b80c355d720a3dadc7e0;hpb=168188f6650dc9a777d57f9c7a8ff1be957bc892 diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index e484cd22..7f81e20e 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -3,7 +3,8 @@ * * 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; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, 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 @@ -23,6 +24,16 @@ #define USB_DEBUG_DATA 0 #define USB_ECHO 0 +#ifndef USE_USB_STDIO +#define USE_USB_STDIO 1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail) +#endif + #if USB_DEBUG #define debug(format, args...) printf(format, ## args); #else @@ -107,9 +118,8 @@ static uint8_t ao_usb_in_pending; * but not pulled to the shadow buffer. */ static uint8_t ao_usb_out_avail; -static uint8_t ao_usb_running; +uint8_t ao_usb_running; static uint8_t ao_usb_configuration; -static uint8_t ueienx_0; #define AO_USB_EP0_GOT_RESET 1 #define AO_USB_EP0_GOT_SETUP 2 @@ -129,7 +139,7 @@ static inline uint32_t set_toggle(uint32_t current_value, static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) { - return (uint32_t *) (stm_usb_sram + 2 * sram_addr); + return (uint32_t *) (((void *) ((uint8_t *) stm_usb_sram + 2 * sram_addr))); } static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { @@ -164,7 +174,7 @@ static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { * Set current device address and mark the * interface as active */ -void +static void ao_usb_set_address(uint8_t address) { debug("ao_usb_set_address %02x\n", address); @@ -303,7 +313,6 @@ ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint3 static void ao_usb_set_ep0(void) { - uint32_t epr; int e; ao_usb_sram_addr = 0; @@ -341,13 +350,24 @@ ao_usb_set_ep0(void) } ao_usb_set_address(0); + + ao_usb_running = 0; + + /* Reset our internal state + */ + + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_data = NULL; + ao_usb_ep0_in_len = 0; + + ao_usb_ep0_out_data = 0; + ao_usb_ep0_out_len = 0; } static void ao_usb_set_configuration(void) { - uint32_t epr; - debug ("ao_usb_set_configuration\n"); /* Set up the INT end point */ @@ -387,7 +407,15 @@ ao_usb_set_configuration(void) STM_USB_EPR_STAT_RX_DISABLED, STM_USB_EPR_STAT_TX_NAK); + ao_usb_in_flushed = 0; + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + + ao_usb_out_avail = 0; + ao_usb_configuration = 0; + ao_usb_running = 1; + ao_wakeup(&ao_usb_running); } static uint16_t control_count; @@ -418,15 +446,11 @@ ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) } static void -ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t bytes) { + uint16_t offset = 0; if (!bytes) return; - if (offset & 1) { - debug_data (" %02x", src[0]); - ao_usb_write_byte(*src++, base, offset++); - bytes--; - } while (bytes >= 2) { debug_data (" %02x %02x", src[0], src[1]); ao_usb_write_short((src[1] << 8) | src[0], base, offset); @@ -503,7 +527,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, 0, this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); debug_data ("\n"); ao_usb_ep0_in_data += this_len; @@ -562,7 +586,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) } static void -ao_usb_ep0_in_start(uint8_t max) +ao_usb_ep0_in_start(uint16_t max) { /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) @@ -570,12 +594,12 @@ ao_usb_ep0_in_start(uint8_t max) ao_usb_ep0_flush(); } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; /* Walk through the list of descriptors and find a match */ static void -ao_usb_get_descriptor(uint16_t value) +ao_usb_get_descriptor(uint16_t value, uint16_t length) { const uint8_t *descriptor; uint8_t type = value >> 8; @@ -589,6 +613,8 @@ ao_usb_get_descriptor(uint16_t value) len = descriptor[2]; else len = descriptor[0]; + if (len > length) + len = length; ao_usb_ep0_in_set(descriptor, len); break; } @@ -633,7 +659,7 @@ ao_usb_ep0_setup(void) break; case AO_USB_REQ_GET_DESCRIPTOR: debug ("get descriptor %d\n", ao_usb_setup.value); - ao_usb_get_descriptor(ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value, ao_usb_setup.length); break; case AO_USB_REQ_GET_CONFIGURATION: debug ("get configuration %d\n", ao_usb_configuration); @@ -721,6 +747,9 @@ ao_usb_ep0_handle(uint8_t receive) if (receive & AO_USB_EP0_GOT_TX_ACK) { debug ("\tgot tx ack\n"); +#if HAS_FLIGHT && AO_USB_FORCE_IDLE + ao_flight_force_idle = 1; +#endif /* Wait until the IN packet is received from addr 0 * before assigning our local address */ @@ -770,7 +799,7 @@ stm_usb_lp_isr(void) _rx_dbg1("RX ISR", epr); ao_usb_out_avail = 1; _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); + ao_wakeup(AO_USB_OUT_SLEEP_ADDR); _rx_dbg0("stdin awoken"); } break; @@ -800,7 +829,7 @@ stm_usb_lp_isr(void) } void -stm_usb_fs_wkup(void) +stm_usb_fs_wkup_isr(void) { /* USB wakeup, just clear the bit for now */ stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); @@ -817,7 +846,7 @@ _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, 0, ao_usb_tx_count); + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); 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); @@ -903,7 +932,7 @@ _ao_usb_out_recv(void) _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); } -int +static int _ao_usb_pollchar(void) { uint8_t c; @@ -936,11 +965,16 @@ ao_usb_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); + ao_sleep(AO_USB_OUT_SLEEP_ADDR); ao_arch_release_interrupts(); return c; } +#ifndef HAS_USB_DISABLE +#define HAS_USB_DISABLE 1 +#endif + +#if HAS_USB_DISABLE void ao_usb_disable(void) { @@ -955,9 +989,10 @@ ao_usb_disable(void) stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES); /* Disable the interface */ - stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN); ao_arch_release_interrupts(); } +#endif void ao_usb_enable(void) @@ -982,7 +1017,7 @@ ao_usb_enable(void) ao_arch_block_interrupts(); /* Route interrupts */ - stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); + stm_nvic_set_priority(STM_ISR_USB_LP_POS, AO_STM_NVIC_LOW_PRIORITY); stm_nvic_set_enable(STM_ISR_USB_LP_POS); ao_usb_configuration = 0; @@ -1044,7 +1079,7 @@ ao_usb_irq(void) control_count, out_count, in_count, int_count, reset_count); } -__code struct ao_cmds ao_usb_cmds[] = { +const struct ao_cmds ao_usb_cmds[] = { { ao_usb_irq, "I\0Show USB interrupt counts" }, { 0, NULL } }; @@ -1064,8 +1099,10 @@ ao_usb_init(void) ao_cmd_register(&ao_usb_cmds[0]); #endif #if !USB_ECHO +#if USE_USB_STDIO ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif +#endif } #if TX_DBG || RX_DBG @@ -1074,7 +1111,7 @@ struct ao_usb_dbg { int line; char *msg; uint32_t value; - uint32_t primask; + uint32_t prival; #if TX_DBG uint16_t in_count; uint32_t in_epr; @@ -1090,19 +1127,23 @@ struct ao_usb_dbg { #endif }; -#define NUM_USB_DBG 128 +#define NUM_USB_DBG 16 -static struct ao_usb_dbg dbg[128]; +static struct ao_usb_dbg dbg[NUM_USB_DBG]; static int dbg_i; static void _dbg(int line, char *msg, uint32_t value) { - uint32_t primask; + uint32_t prival; dbg[dbg_i].line = line; dbg[dbg_i].msg = msg; dbg[dbg_i].value = value; - asm("mrs %0,primask" : "=&r" (primask)); - dbg[dbg_i].primask = primask; +#if AO_NONMASK_INTERRUPT + asm("mrs %0,basepri" : "=&r" (prival)); +#else + asm("mrs %0,primask" : "=&r" (prival)); +#endif + dbg[dbg_i].prival = prival; #if TX_DBG dbg[dbg_i].in_count = in_count; dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR];