Explorar o código

Merge branch 'hathach:master' into feature-kuiic

nxf58843 %!s(int64=4) %!d(string=hai) anos
pai
achega
51e24dd4f8

+ 1 - 1
README.rst

@@ -50,7 +50,7 @@ The stack supports the following MCUs:
 - **Renesas:** RX63N, RX65N, RX72N
 - **Silabs:** EFM32GG
 - **Sony:** CXD56
-- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, L0, L1, L4, L4+
+- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+
 - **TI:** MSP430, MSP432E4, TM4C123
 - **ValentyUSB:** eptri
 

+ 13 - 7
docs/reference/supported.rst

@@ -82,6 +82,8 @@ Supported MCUs
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
 |              | H7                    | ✔      |      | ✔         | dwc2              |              |
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | G4                    | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
 |              | L0, L1                | ✔      | ✖    | ✖         | stm32_fsdev       |              |
 |              +----+------------------+--------+------+-----------+-------------------+--------------+
 |              | L4 | 4x2, 4x3         | ✔      | ✖    | ✖         | stm32_fsdev       |              |
@@ -352,6 +354,17 @@ F7
 -  `STM32 F767zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-f767zi.html>`__
 -  `STM32 F769i Discovery <https://www.st.com/en/evaluation-tools/32f769idiscovery.html>`__
 
+H7
+^^
+-  `STM32 H743zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-h743zi.html>`__
+-  `STM32 H743i Evaluation <https://www.st.com/en/evaluation-tools/stm32h743i-eval.html>`__
+-  `STM32 H745i Discovery <https://www.st.com/en/evaluation-tools/stm32h745i-disco.html>`__
+-  `Waveshare OpenH743I-C <https://www.waveshare.com/openh743i-c-standard.htm>`__
+
+G4
+^^
+-  `STM32 G474RE Nucleo <https://www.st.com/en/evaluation-tools/nucleo-g474re.html>`__
+
 L0
 ^^
 -  `STM32 L035c8 Discovery <https://www.st.com/en/evaluation-tools/32l0538discovery.html>`__
@@ -362,13 +375,6 @@ L4
 -  `STM32 L4P5zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html>`__
 -  `STM32 L4R5zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html>`__
 
-H7
-^^
--  `STM32 H743zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-h743zi.html>`__
--  `STM32 H743i Evaluation <https://www.st.com/en/evaluation-tools/stm32h743i-eval.html>`__
--  `STM32 H745i Discovery <https://www.st.com/en/evaluation-tools/stm32h745i-disco.html>`__
--  `Waveshare OpenH743I-C <https://www.waveshare.com/openh743i-c-standard.htm>`__
-
 TI
 --
 

+ 17 - 15
examples/device/hid_generic_inout/hid_test.py

@@ -1,20 +1,22 @@
 # Install python3 HID package https://pypi.org/project/hid/
 import hid
 
-USB_VID = 0xcafe
+# default is TinyUSB (0xcafe), Adafruit (0x239a), RaspberryPi (0x2e8a), Espressif (0x303a) VID
+USB_VID = (0xcafe, 0x239a, 0x2e8a, 0x303a)
 
-print("Openning HID device with VID = 0x%X" % USB_VID)
+print("VID list: " + ", ".join('%02x' % v for v in USB_VID))
 
-for dict in hid.enumerate(USB_VID):
-    print(dict)
-    dev = hid.Device(dict['vendor_id'], dict['product_id'])
-    if dev:
-        while True:
-            # Get input from console and encode to UTF8 for array of chars.
-            # hid generic inout is single report therefore by HIDAPI requirement
-            # it must be preceeded with 0x00 as dummy reportID
-            str_out = b'\x00'
-            str_out += input("Send text to HID Device : ").encode('utf-8')
-            dev.write(str_out)
-            str_in = dev.read(64)
-            print("Received from HID Device:", str_in, '\n')
+for vid in  USB_VID:
+    for dict in hid.enumerate(vid):
+        print(dict)
+        dev = hid.Device(dict['vendor_id'], dict['product_id'])
+        if dev:
+            while True:
+                # Get input from console and encode to UTF8 for array of chars.
+                # hid generic inout is single report therefore by HIDAPI requirement
+                # it must be preceeded with 0x00 as dummy reportID
+                str_out = b'\x00'
+                str_out += input("Send text to HID Device : ").encode('utf-8')
+                dev.write(str_out)
+                str_in = dev.read(64)
+                print("Received from HID Device:", str_in, '\n')

+ 20 - 16
hw/bsp/stm32g4/boards/stm32g474nucleo/board.h

@@ -32,8 +32,8 @@
 #endif
 
 // G474RE Nucleo does not has usb connection. We need to manually connect
-// - PA11 for D+, CN10.14
-// - PA12 for D-, CN10.12
+// - PA12 for D+, CN10.12
+// - PA11 for D-, CN10.14
 
 // LED
 #define LED_PORT              GPIOA
@@ -61,32 +61,36 @@ static inline void board_clock_init(void)
 {
   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
   // Configure the main internal regulator output voltage
   HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
 
   // Initializes the CPU, AHB and APB busses clocks
-  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
-  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
-  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
-  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
-  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
-  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
-  RCC_OscInitStruct.PLL.PLLN = 85;
-  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
-  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
-  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSE;
+  RCC_OscInitStruct.HSEState       = RCC_HSE_ON;
+  RCC_OscInitStruct.HSI48State     = RCC_HSI48_ON;
+  RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
+  RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_HSE;
+  RCC_OscInitStruct.PLL.PLLM       = RCC_PLLM_DIV4;
+  RCC_OscInitStruct.PLL.PLLN       = 50;
+  RCC_OscInitStruct.PLL.PLLP       = RCC_PLLP_DIV2;
+  RCC_OscInitStruct.PLL.PLLQ       = RCC_PLLQ_DIV2;
+  RCC_OscInitStruct.PLL.PLLR       = RCC_PLLR_DIV2;
   HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
   // Initializes the CPU, AHB and APB busses clocks
-  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
-  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
-  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+  RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
+  RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
+  RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;
   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
-
   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8);
 
+  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
+  PeriphClkInit.UsbClockSelection    = RCC_USBCLKSOURCE_HSI48;
+  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) ;
+
 #if 0 // TODO need to check if USB clock is enabled
   /* Enable HSI48 */
   memset(&RCC_OscInitStruct, 0, sizeof(RCC_OscInitStruct));

+ 3 - 1
hw/bsp/stm32g4/boards/stm32g474nucleo/board.mk

@@ -1,4 +1,6 @@
-CFLAGS += -DSTM32G474xx
+CFLAGS += \
+	-DSTM32G474xx \
+	-DHSE_VALUE=24000000
 
 LD_FILE = $(BOARD_PATH)/STM32G474RETx_FLASH.ld
 

+ 7 - 7
hw/bsp/stm32g4/family.c

@@ -118,13 +118,13 @@ void board_init(void)
 
   // USB Pins TODO double check USB clock and pin setup
   // Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
-//  GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
-//  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
-//  GPIO_InitStruct.Pull = GPIO_NOPULL;
-//  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
-//  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-//
-//  __HAL_RCC_USB_CLK_ENABLE();
+  GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
+  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+  __HAL_RCC_USB_CLK_ENABLE();
 
   board_vbus_sense_init();
 }

+ 27 - 11
src/portable/raspberrypi/rp2040/dcd_rp2040.c

@@ -83,7 +83,7 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
 
   assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0);
   uint dpram_offset = hw_data_offset(ep->hw_data_buf);
-  assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
+  hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
 
   pico_info("  Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
 
@@ -93,7 +93,6 @@ static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
   *ep->endpoint_control = reg;
 }
 
-#if 0 // todo unused
 static void _hw_endpoint_close(struct hw_endpoint *ep)
 {
     // Clear hardware registers and then zero the struct
@@ -103,6 +102,21 @@ static void _hw_endpoint_close(struct hw_endpoint *ep)
     *ep->buffer_control = 0;
     // Clear any endpoint state
     memset(ep, 0, sizeof(struct hw_endpoint));
+
+    // Reclaim buffer space if all endpoints are closed
+    bool reclaim_buffers = true;
+    for ( uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++ )
+    {
+        if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL || hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL)
+        {
+            reclaim_buffers = false;
+            break;
+        }
+    }
+    if (reclaim_buffers)
+    {
+        next_buffer_ptr = &usb_dpram->epx_data[0];
+    }
 }
 
 static void hw_endpoint_close(uint8_t ep_addr)
@@ -110,7 +124,6 @@ static void hw_endpoint_close(uint8_t ep_addr)
     struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
     _hw_endpoint_close(ep);
 }
-#endif
 
 static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
 {
@@ -224,6 +237,8 @@ static void reset_non_control_endpoints(void)
 
   // clear non-control hw endpoints
   tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t));
+
+  // reclaim buffer space
   next_buffer_ptr = &usb_dpram->epx_data[0];
 }
 
@@ -232,6 +247,14 @@ static void dcd_rp2040_irq(void)
     uint32_t const status = usb_hw->ints;
     uint32_t handled = 0;
 
+    // xfer events are handled before setup req. So if a transfer completes immediately
+    // before closing the EP, the events will be delivered in same order.
+    if (status & USB_INTS_BUFF_STATUS_BITS)
+    {
+        handled |= USB_INTS_BUFF_STATUS_BITS;
+        hw_handle_buff_status();
+    }
+
     if (status & USB_INTS_SETUP_REQ_BITS)
     {
         handled |= USB_INTS_SETUP_REQ_BITS;
@@ -245,12 +268,6 @@ static void dcd_rp2040_irq(void)
         usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
     }
 
-    if (status & USB_INTS_BUFF_STATUS_BITS)
-    {
-        handled |= USB_INTS_BUFF_STATUS_BITS;
-        hw_handle_buff_status();
-    }
-
 #if FORCE_VBUS_DETECT == 0
     // Since we force VBUS detect On, device will always think it is connected and
     // couldn't distinguish between disconnect and suspend
@@ -479,10 +496,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
 void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
 {
     (void) rhport;
-    (void) ep_addr;
 
-    // usbd.c says: In progress transfers on this EP may be delivered after this call
     pico_trace("dcd_edpt_close %02x\n", ep_addr);
+    hw_endpoint_close(ep_addr);
 }
 
 void dcd_int_handler(uint8_t rhport)

+ 1 - 1
src/portable/raspberrypi/rp2040/rp2040_usb.c

@@ -294,7 +294,7 @@ bool hw_endpoint_xfer_continue(struct hw_endpoint *ep)
   // Part way through a transfer
   if (!ep->active)
   {
-    panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string);
+    panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
   }
 
   // Update EP struct from hardware state