altos: Work on MAX6691 driver
[fw/altos] / src / stm / ao_usb_stm.c
index b00390ec0318b14901a68156ad29597df5b08f2f..7f81e20e67c01b948f9703659ffc3c1acf4b87ca 100644 (file)
@@ -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
@@ -117,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
@@ -139,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) {
@@ -174,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);
@@ -313,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;
@@ -351,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 */
@@ -397,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;
@@ -428,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);
@@ -513,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;
 
@@ -580,12 +594,12 @@ ao_usb_ep0_in_start(uint16_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;
@@ -599,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;
                }
@@ -643,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);
@@ -731,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
                 */
@@ -810,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);
@@ -827,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);
@@ -913,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;
@@ -951,6 +970,11 @@ ao_usb_getchar(void)
        return c;
 }
 
+#ifndef HAS_USB_DISABLE
+#define HAS_USB_DISABLE 1
+#endif
+
+#if HAS_USB_DISABLE
 void
 ao_usb_disable(void)
 {
@@ -965,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)
@@ -992,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;
@@ -1054,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 }
 };
@@ -1086,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;
@@ -1102,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];