This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ebc8a7291d arm/stm32g0: Add USB device controller support
4ebc8a7291d is described below

commit 4ebc8a7291df955dece09073b8798db2dfd6490b
Author: jsanchez-2g <[email protected]>
AuthorDate: Thu Aug 20 13:29:16 2026 -0500

    arm/stm32g0: Add USB device controller support
    
    Add the STM32G0 USB interrupt, memory map, register layout, HSI48 clocking, 
power control, packet memory handling, and device-controller support.
    
    Assisted-by: OpenAI Codex
    Signed-off-by: jsanchez-2g <[email protected]>
---
 arch/arm/include/stm32g0/irq.h                     |   1 +
 .../src/common/stm32/hardware/stm32_usbdev_m0.h    | 103 ++++++++------
 arch/arm/src/common/stm32/stm32_pwr.h              |  19 +++
 arch/arm/src/common/stm32/stm32_pwr_m0_g0.c        |  46 +++++++
 arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c     | 153 +++++++++++++++++++--
 arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h  |   3 +
 arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h     |   5 +
 arch/arm/src/stm32g0/hardware/stm32g0_pwr.h        |   1 +
 arch/arm/src/stm32g0/hardware/stm32g0_rcc.h        |   9 +-
 arch/arm/src/stm32g0/stm32_rcc.c                   |   6 +
 arch/arm/src/stm32g0/stm32g0_rcc.c                 |  18 +++
 11 files changed, 314 insertions(+), 50 deletions(-)

diff --git a/arch/arm/include/stm32g0/irq.h b/arch/arm/include/stm32g0/irq.h
index 1edbcd2b850..4d4b3c98ff4 100644
--- a/arch/arm/include/stm32g0/irq.h
+++ b/arch/arm/include/stm32g0/irq.h
@@ -90,6 +90,7 @@
 #else
 #  define STM32_IRQ_UCPD12     (STM32_IRQ_EXTINT + 8)  /* 8: UCPD1_2 */
 #  define STM32_IRQ_EXTI32_33  (STM32_IRQ_EXTINT + 8)  /* 8: EXTI_32_33 */
+#  define STM32_IRQ_USB        (STM32_IRQ_EXTINT + 8)  /* 8: USB */
 #endif
 
 #define STM32_IRQ_DMA1CH1      (STM32_IRQ_EXTINT + 9)  /* 9: DMA1_CH1 */
diff --git a/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h 
b/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h
index 80c3445f962..9af1c4f14bd 100644
--- a/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h
+++ b/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h
@@ -40,39 +40,44 @@
 
 /* Endpoint Registers */
 
-#define STM32_USB_EPR_OFFSET(n)      ((n) << 2) /* USB endpoint n register 
(16-bits) */
+#define STM32_USB_EPR_OFFSET(n)      ((n) << 2)
 
-#define STM32_USB_EP0R_OFFSET        0x0000  /* USB endpoint 0 register 
(16-bits) */
-#define STM32_USB_EP1R_OFFSET        0x0004  /* USB endpoint 1 register 
(16-bits) */
-#define STM32_USB_EP2R_OFFSET        0x0008  /* USB endpoint 2 register 
(16-bits) */
-#define STM32_USB_EP3R_OFFSET        0x000c  /* USB endpoint 3 register 
(16-bits) */
-#define STM32_USB_EP4R_OFFSET        0x0010  /* USB endpoint 4 register 
(16-bits) */
-#define STM32_USB_EP5R_OFFSET        0x0014  /* USB endpoint 5 register 
(16-bits) */
-#define STM32_USB_EP6R_OFFSET        0x0018  /* USB endpoint 6 register 
(16-bits) */
-#define STM32_USB_EP7R_OFFSET        0x001c  /* USB endpoint 7 register 
(16-bits) */
+#define STM32_USB_EP0R_OFFSET        0x0000  /* USB endpoint 0 register */
+#define STM32_USB_EP1R_OFFSET        0x0004  /* USB endpoint 1 register */
+#define STM32_USB_EP2R_OFFSET        0x0008  /* USB endpoint 2 register */
+#define STM32_USB_EP3R_OFFSET        0x000c  /* USB endpoint 3 register */
+#define STM32_USB_EP4R_OFFSET        0x0010  /* USB endpoint 4 register */
+#define STM32_USB_EP5R_OFFSET        0x0014  /* USB endpoint 5 register */
+#define STM32_USB_EP6R_OFFSET        0x0018  /* USB endpoint 6 register */
+#define STM32_USB_EP7R_OFFSET        0x001c  /* USB endpoint 7 register */
 
 /* Common Registers */
 
-#define STM32_USB_CNTR_OFFSET        0x0040  /* USB control register (16-bits) 
*/
-#define STM32_USB_ISTR_OFFSET        0x0044  /* USB interrupt status register 
(16-bits) */
-#define STM32_USB_FNR_OFFSET         0x0048  /* USB frame number register 
(16-bits) */
-#define STM32_USB_DADDR_OFFSET       0x004c  /* USB device address (16-bits) */
-#define STM32_USB_BTABLE_OFFSET      0x0050  /* Buffer table address (16-bits) 
*/
-#define STM32_USB_LPMCSR_OFFSET      0x0054  /* LPM control and status 
register (16-bits) */
-#define STM32_USB_BCDR_OFFSET        0x0058  /* Battery charging detector 
(16-bits) */
+#define STM32_USB_CNTR_OFFSET        0x0040  /* USB control register */
+#define STM32_USB_ISTR_OFFSET        0x0044  /* USB interrupt status register 
*/
+#define STM32_USB_FNR_OFFSET         0x0048  /* USB frame number register */
+#define STM32_USB_DADDR_OFFSET       0x004c  /* USB device address */
+#ifndef CONFIG_STM32_STM32G0
+#  define STM32_USB_BTABLE_OFFSET    0x0050  /* Buffer table address (16-bits) 
*/
+#endif
+#define STM32_USB_LPMCSR_OFFSET      0x0054  /* LPM control and status 
register */
+#define STM32_USB_BCDR_OFFSET        0x0058  /* Battery charging detector */
 
-/* Buffer Descriptor Table (Relatative to BTABLE address) */
-
-#define STM32_USB_ADDR_TX_WOFFSET    (0)     /* Transmission buffer address n 
(16-bits) */
-#define STM32_USB_COUNT_TX_WOFFSET   (2)     /* Transmission byte count n 
(16-bits) */
-#define STM32_USB_ADDR_RX_WOFFSET    (4)     /* Reception buffer address n 
(16-bits) */
-#define STM32_USB_COUNT_RX_WOFFSET   (6)     /* Reception byte count n 
(16-bits) */
+/* Buffer Descriptor Table (Relative to BTABLE address) */
 
-#define STM32_USB_BTABLE_RADDR(ep,o) (((uint32_t)getreg16(STM32_USB_BTABLE) + 
((ep) << 3)) + (o))
-#define STM32_USB_ADDR_TX_OFFSET(ep)  
STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_TX_WOFFSET)
-#define STM32_USB_COUNT_TX_OFFSET(ep) 
STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_TX_WOFFSET)
-#define STM32_USB_ADDR_RX_OFFSET(ep)  
STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_RX_WOFFSET)
-#define STM32_USB_COUNT_RX_OFFSET(ep) 
STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_RX_WOFFSET)
+#ifdef CONFIG_STM32_STM32G0
+#  define STM32_USB_TX_WOFFSET       (0)     /* Transmission descriptor n 
(32-bits) */
+#  define STM32_USB_RX_WOFFSET       (4)     /* Reception descriptor n 
(32-bits) */
+#  define STM32_USB_BTABLE_RADDR(ep,o) \
+    (STM32_USBRAM_BASE + ((ep) << 3) + (o))
+#else
+#  define STM32_USB_ADDR_TX_WOFFSET  (0)     /* Transmission buffer address n 
(16-bits) */
+#  define STM32_USB_COUNT_TX_WOFFSET (2)     /* Transmission byte count n 
(16-bits) */
+#  define STM32_USB_ADDR_RX_WOFFSET  (4)     /* Reception buffer address n 
(16-bits) */
+#  define STM32_USB_COUNT_RX_WOFFSET (6)     /* Reception byte count n 
(16-bits) */
+#  define STM32_USB_BTABLE_RADDR(ep,o) \
+    ((uint32_t)getreg16(STM32_USB_BTABLE) + ((ep) << 3) + (o))
+#endif
 
 /* Register Addresses *******************************************************/
 
@@ -94,17 +99,26 @@
 #define STM32_USB_ISTR               (STM32_USB_BASE + STM32_USB_ISTR_OFFSET)
 #define STM32_USB_FNR                (STM32_USB_BASE + STM32_USB_FNR_OFFSET)
 #define STM32_USB_DADDR              (STM32_USB_BASE + STM32_USB_DADDR_OFFSET)
-#define STM32_USB_BTABLE             (STM32_USB_BASE + STM32_USB_BTABLE_OFFSET)
+#ifndef CONFIG_STM32_STM32G0
+#  define STM32_USB_BTABLE           (STM32_USB_BASE + STM32_USB_BTABLE_OFFSET)
+#endif
 #define STM32_USB_LPMCSR             (STM32_USB_BASE + STM32_USB_LPMCSR_OFFSET)
 #define STM32_USB_BCDR               (STM32_USB_BASE + STM32_USB_BCDR_OFFSET)
 
 /* Buffer Descriptor Table (Relative to BTABLE address) */
 
-#define STM32_USB_BTABLE_ADDR(ep,o)  (STM32_USBRAM_BASE + 
STM32_USB_BTABLE_RADDR(ep,o))
-#define STM32_USB_ADDR_TX(ep)        
STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_TX_WOFFSET)
-#define STM32_USB_COUNT_TX(ep)       
STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_TX_WOFFSET)
-#define STM32_USB_ADDR_RX(ep)        
STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_RX_WOFFSET)
-#define STM32_USB_COUNT_RX(ep)       
STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_RX_WOFFSET)
+#ifdef CONFIG_STM32_STM32G0
+#  define STM32_USB_BTABLE_ADDR(ep,o) STM32_USB_BTABLE_RADDR(ep,o)
+#  define STM32_USB_TX(ep)           
STM32_USB_BTABLE_RADDR(ep,STM32_USB_TX_WOFFSET)
+#  define STM32_USB_RX(ep)           
STM32_USB_BTABLE_RADDR(ep,STM32_USB_RX_WOFFSET)
+#else
+#  define STM32_USB_BTABLE_ADDR(ep,o) \
+    (STM32_USBRAM_BASE + STM32_USB_BTABLE_RADDR(ep,o))
+#  define STM32_USB_ADDR_TX(ep)      
STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_TX_WOFFSET)
+#  define STM32_USB_COUNT_TX(ep)     
STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_TX_WOFFSET)
+#  define STM32_USB_ADDR_RX(ep)      
STM32_USB_BTABLE_ADDR(ep,STM32_USB_ADDR_RX_WOFFSET)
+#  define STM32_USB_COUNT_RX(ep)     
STM32_USB_BTABLE_ADDR(ep,STM32_USB_COUNT_RX_WOFFSET)
+#endif
 
 /* Register Bitfield Definitions ********************************************/
 
@@ -239,16 +253,27 @@
 
 /* Reception buffer address */
 
-#define USB_ADDR_RX_ZERO               (1 << 0)  /* Bit 0 This bit must always 
be written as ‘0’ */
-#define USB_ADDR_RX_SHIFT              (1)       /* Bits 15:1 ADDRn_RX[15:1]: 
Reception Buffer Address */
-#define USB_ADDR_RX_MASK               (0x7fff << USB_ADDR_RX_SHIFT)
+#ifdef CONFIG_STM32_STM32G0
+#  define USB_ADDR_RX_SHIFT            (2)       /* Bits 15:2: Reception 
buffer address */
+#  define USB_ADDR_RX_MASK             (0x3fff << USB_ADDR_RX_SHIFT)
+#else
+#  define USB_ADDR_RX_ZERO             (1 << 0)  /* Bit 0 must always be 
written as zero */
+#  define USB_ADDR_RX_SHIFT            (1)       /* Bits 15:1: Reception 
buffer address */
+#  define USB_ADDR_RX_MASK             (0x7fff << USB_ADDR_RX_SHIFT)
+#endif
 
 /* Reception byte count */
 
-#define USB_COUNT_RX_BL_SIZE           (1 << 15) /* Bit 15: BLock SIZE. */
-#define USB_COUNT_RX_NUM_BLOCK_SHIFT   (10)      /* Bits 14-10: Number of 
blocks */
+#ifdef CONFIG_STM32_STM32G0
+#  define USB_COUNT_RX_BL_SIZE         (1 << 31) /* Bit 31: Block size */
+#  define USB_COUNT_RX_NUM_BLOCK_SHIFT (26)      /* Bits 30-26: Number of 
blocks */
+#  define USB_COUNT_RX_SHIFT           (16)      /* Bits 25-16: Reception byte 
count */
+#else
+#  define USB_COUNT_RX_BL_SIZE         (1 << 15) /* Bit 15: Block size */
+#  define USB_COUNT_RX_NUM_BLOCK_SHIFT (10)      /* Bits 14-10: Number of 
blocks */
+#  define USB_COUNT_RX_SHIFT           (0)       /* Bits 9-0: Reception byte 
count */
+#endif
 #define USB_COUNT_RX_NUM_BLOCK_MASK    (0x1f << USB_COUNT_RX_NUM_BLOCK_SHIFT)
-#define USB_COUNT_RX_SHIFT             (0)       /* Bits 9-0: Reception Byte 
Count */
 #define USB_COUNT_RX_MASK              (0x03ff << USB_COUNT_RX_SHIFT)
 
 #endif /* CONFIG_STM32_HAVE_USBDEV */
diff --git a/arch/arm/src/common/stm32/stm32_pwr.h 
b/arch/arm/src/common/stm32/stm32_pwr.h
index 9de201ed61e..4e41b05c465 100644
--- a/arch/arm/src/common/stm32/stm32_pwr.h
+++ b/arch/arm/src/common/stm32/stm32_pwr.h
@@ -216,6 +216,25 @@ void stm32_pwr_enablebreg(bool region);
 void stm32_pwr_setvos(uint16_t vos);
 #endif
 
+/****************************************************************************
+ * Name: stm32_pwr_enableusv
+ *
+ * Description:
+ *   Declare the USB supply valid or not valid.  The USB transceiver cannot
+ *   be used on STM32G0 until the supply has been declared valid.
+ *
+ * Input Parameters:
+ *   enable - True:  USB supply is valid; False: USB supply is not valid.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_STM32G0
+void stm32_pwr_enableusv(bool enable);
+#endif
+
 /****************************************************************************
  * Name: stm32_pwr_setpvd
  *
diff --git a/arch/arm/src/common/stm32/stm32_pwr_m0_g0.c 
b/arch/arm/src/common/stm32/stm32_pwr_m0_g0.c
index d1627f7fa5f..7dbda38f4ac 100644
--- a/arch/arm/src/common/stm32/stm32_pwr_m0_g0.c
+++ b/arch/arm/src/common/stm32/stm32_pwr_m0_g0.c
@@ -34,6 +34,7 @@
 #include <nuttx/irq.h>
 
 #include "arm_internal.h"
+#include "hardware/stm32_rcc.h"
 #include "stm32_pwr.h"
 
 #if defined(CONFIG_STM32_PWR)
@@ -91,6 +92,51 @@ void stm32_pwr_setvos(uint16_t vos)
     }
 }
 
+/****************************************************************************
+ * Name: stm32_pwr_enableusv
+ *
+ * Description:
+ *   Declare the USB supply valid or not valid.  The USB transceiver cannot
+ *   be used on STM32G0 until the supply has been declared valid.
+ *
+ * Input Parameters:
+ *   enable - True:  USB supply is valid; False: USB supply is not valid.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_STM32G0
+void stm32_pwr_enableusv(bool enable)
+{
+  uint32_t regval;
+  bool wasenabled;
+
+  regval = getreg32(STM32_RCC_APB1ENR);
+  wasenabled = (regval & RCC_APB1ENR_PWREN) != 0;
+
+  if (!wasenabled)
+    {
+      modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_PWREN);
+    }
+
+  if (enable)
+    {
+      modifyreg32(STM32_PWR_CR2, 0, PWR_CR2_USV);
+    }
+  else
+    {
+      modifyreg32(STM32_PWR_CR2, PWR_CR2_USV, 0);
+    }
+
+  if (!wasenabled)
+    {
+      modifyreg32(STM32_RCC_APB1ENR, RCC_APB1ENR_PWREN, 0);
+    }
+}
+#endif
+
 /* TODO Other stm32_pwr_* functions need to be implemented */
 
 #endif /* CONFIG_STM32_PWR */
diff --git a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c 
b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c
index af2660767ab..d0bf8eae531 100644
--- a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c
+++ b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c
@@ -53,6 +53,7 @@
 #include "hardware/stm32_rcc.h"
 #include "hardware/stm32_usbdev.h"
 #include "stm32_gpio.h"
+#include "stm32_pwr.h"
 #include "stm32_usbdev.h"
 
 #if defined(CONFIG_USBDEV) && defined(CONFIG_STM32_USB)
@@ -352,12 +353,17 @@ struct stm32_usbdev_s
 /* Register operations ******************************************************/
 
 #ifdef CONFIG_STM32_USBDEV_REGDEBUG
-static uint16_t stm32_getreg(uint32_t addr);
-static void stm32_putreg(uint16_t val, uint32_t addr);
+static uint32_t stm32_getreg(uint32_t addr);
+static void stm32_putreg(uint32_t val, uint32_t addr);
 static void stm32_dumpep(int epno);
 #else
-#  define stm32_getreg(addr)     getreg16(addr)
-#  define stm32_putreg(val,addr) putreg16(val,addr)
+#  ifdef CONFIG_STM32_STM32G0
+#    define stm32_getreg(addr)     getreg32(addr)
+#    define stm32_putreg(val,addr) putreg32(val,addr)
+#  else
+#    define stm32_getreg(addr)     getreg16(addr)
+#    define stm32_putreg(val,addr) putreg16(val,addr)
+#  endif
 #  define stm32_dumpep(epno)
 #endif
 
@@ -600,15 +606,19 @@ const struct trace_msg_t g_usb_trace_strings_deverror[] =
  ****************************************************************************/
 
 #ifdef CONFIG_STM32_USBDEV_REGDEBUG
-static uint16_t stm32_getreg(uint32_t addr)
+static uint32_t stm32_getreg(uint32_t addr)
 {
   static uint32_t prevaddr = 0;
-  static uint16_t preval = 0;
+  static uint32_t preval = 0;
   static uint32_t count = 0;
 
   /* Read the value from the register */
 
-  uint16_t val = getreg16(addr);
+#ifdef CONFIG_STM32_STM32G0
+  uint32_t val = getreg32(addr);
+#else
+  uint32_t val = getreg16(addr);
+#endif
 
   /* Is this the same value that we read from the same register last time?
    * Are we polling the register?  If so, suppress some of the output.
@@ -658,7 +668,7 @@ static uint16_t stm32_getreg(uint32_t addr)
  ****************************************************************************/
 
 #ifdef CONFIG_STM32_USBDEV_REGDEBUG
-static void stm32_putreg(uint16_t val, uint32_t addr)
+static void stm32_putreg(uint32_t val, uint32_t addr)
 {
   /* Show the register value being written */
 
@@ -666,7 +676,11 @@ static void stm32_putreg(uint16_t val, uint32_t addr)
 
   /* Write the value */
 
+#ifdef CONFIG_STM32_STM32G0
+  putreg32(val, addr);
+#else
   putreg16(val, addr);
+#endif
 }
 #endif
 
@@ -679,6 +693,27 @@ static void stm32_dumpep(int epno)
 {
   uint32_t addr;
 
+#ifdef CONFIG_STM32_STM32G0
+  uinfo("CNTR:   %04" PRIx32 "\n", getreg32(STM32_USB_CNTR));
+  uinfo("ISTR:   %04" PRIx32 "\n", getreg32(STM32_USB_ISTR));
+  uinfo("FNR:    %04" PRIx32 "\n", getreg32(STM32_USB_FNR));
+  uinfo("DADDR:  %04" PRIx32 "\n", getreg32(STM32_USB_DADDR));
+
+  addr = STM32_USB_EPR(epno);
+  uinfo("EPR%d:   [%08" PRIx32 "] %04" PRIx32 "\n",
+        epno, addr, getreg32(addr));
+
+  addr = STM32_USB_BTABLE_ADDR(epno, 0);
+  uinfo("DESC:   %08" PRIx32 "\n", addr);
+
+  addr = STM32_USB_TX(epno);
+  uinfo("  TX BUF:  [%08" PRIx32 "] %08" PRIx32 "\n",
+        addr, getreg32(addr));
+
+  addr = STM32_USB_RX(epno);
+  uinfo("  RX BUF:  [%08" PRIx32 "] %08" PRIx32 "\n",
+        addr, getreg32(addr));
+#else
   /* Common registers */
 
   uinfo("CNTR:   %04x\n", getreg16(STM32_USB_CNTR));
@@ -710,6 +745,7 @@ static void stm32_dumpep(int epno)
 
   addr = STM32_USB_COUNT_RX(epno);
   uinfo("     COUNT: [%08" PRIx32 "] %04x\n",  addr, getreg16(addr));
+#endif
 }
 #endif
 
@@ -723,8 +759,13 @@ static void stm32_dumpep(int epno)
 
 static inline void stm32_seteptxcount(uint8_t epno, uint16_t count)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *epaddr = (uint32_t *)STM32_USB_TX(epno);
+  *epaddr = (*epaddr & 0x0000ffff) | ((uint32_t)count << 16);
+#else
   volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_TX(epno);
   *epaddr = count;
+#endif
 }
 
 /****************************************************************************
@@ -733,8 +774,13 @@ static inline void stm32_seteptxcount(uint8_t epno, 
uint16_t count)
 
 static inline void stm32_seteptxaddr(uint8_t epno, uint16_t addr)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *txaddr = (uint32_t *)STM32_USB_TX(epno);
+  *txaddr = (*txaddr & 0xffff0000) | addr;
+#else
   volatile uint16_t *txaddr = (uint16_t *)STM32_USB_ADDR_TX(epno);
   *txaddr = addr;
+#endif
 }
 
 /****************************************************************************
@@ -743,7 +789,11 @@ static inline void stm32_seteptxaddr(uint8_t epno, 
uint16_t addr)
 
 static inline uint16_t stm32_geteptxaddr(uint8_t epno)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *txaddr = (uint32_t *)STM32_USB_TX(epno);
+#else
   volatile uint16_t *txaddr = (uint16_t *)STM32_USB_ADDR_TX(epno);
+#endif
   return (uint16_t)*txaddr;
 }
 
@@ -753,7 +803,11 @@ static inline uint16_t stm32_geteptxaddr(uint8_t epno)
 
 static void stm32_seteprxcount(uint8_t epno, uint16_t count)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *epaddr = (uint32_t *)STM32_USB_RX(epno);
+#else
   volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_RX(epno);
+#endif
   uint32_t rxcount = 0;
   uint16_t nblocks;
 
@@ -793,7 +847,11 @@ static void stm32_seteprxcount(uint8_t epno, uint16_t 
count)
       DEBUGASSERT(nblocks > 0 && nblocks < 0x1f);
       rxcount = (uint32_t)(nblocks << USB_COUNT_RX_NUM_BLOCK_SHIFT);
     }
+#ifdef CONFIG_STM32_STM32G0
+  *epaddr = (*epaddr & 0x0000ffff) | rxcount;
+#else
   *epaddr = rxcount;
+#endif
 }
 
 /****************************************************************************
@@ -802,8 +860,13 @@ static void stm32_seteprxcount(uint8_t epno, uint16_t 
count)
 
 static inline uint16_t stm32_geteprxcount(uint8_t epno)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *epaddr = (uint32_t *)STM32_USB_RX(epno);
+  return (uint16_t)((*epaddr & USB_COUNT_RX_MASK) >> 16);
+#else
   volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_RX(epno);
   return (*epaddr) & USB_COUNT_RX_MASK;
+#endif
 }
 
 /****************************************************************************
@@ -812,8 +875,13 @@ static inline uint16_t stm32_geteprxcount(uint8_t epno)
 
 static inline void stm32_seteprxaddr(uint8_t epno, uint16_t addr)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *rxaddr = (uint32_t *)STM32_USB_RX(epno);
+  *rxaddr = (*rxaddr & 0xffff0000) | addr;
+#else
   volatile uint16_t *rxaddr = (uint16_t *)STM32_USB_ADDR_RX(epno);
   *rxaddr = addr;
+#endif
 }
 
 /****************************************************************************
@@ -822,7 +890,11 @@ static inline void stm32_seteprxaddr(uint8_t epno, 
uint16_t addr)
 
 static inline uint16_t stm32_geteprxaddr(uint8_t epno)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *rxaddr = (uint32_t *)STM32_USB_RX(epno);
+#else
   volatile uint16_t *rxaddr = (uint16_t *)STM32_USB_ADDR_RX(epno);
+#endif
   return (uint16_t)*rxaddr;
 }
 
@@ -1042,6 +1114,36 @@ static inline bool stm32_eprxstalled(uint8_t epno)
 static void stm32_copytopma(const uint8_t *buffer,
                             uint16_t pma, uint16_t nbytes)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *dest;
+
+  dest = (uint32_t *)(STM32_USBRAM_BASE + (uint32_t)pma);
+  while (nbytes >= 4)
+    {
+      *dest++ = (uint32_t)buffer[0] | ((uint32_t)buffer[1] << 8) |
+                ((uint32_t)buffer[2] << 16) |
+                ((uint32_t)buffer[3] << 24);
+      buffer += 4;
+      nbytes -= 4;
+    }
+
+  if (nbytes > 0)
+    {
+      uint32_t value = buffer[0];
+
+      if (nbytes > 1)
+        {
+          value |= (uint32_t)buffer[1] << 8;
+        }
+
+      if (nbytes > 2)
+        {
+          value |= (uint32_t)buffer[2] << 16;
+        }
+
+      *dest = value;
+    }
+#else
   uint16_t *dest;
   uint16_t  ms;
   uint16_t  ls;
@@ -1061,6 +1163,7 @@ static void stm32_copytopma(const uint8_t *buffer,
 
       dest++;
     }
+#endif
 }
 
 /****************************************************************************
@@ -1070,6 +1173,25 @@ static void stm32_copytopma(const uint8_t *buffer,
 static inline void
 stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes)
 {
+#ifdef CONFIG_STM32_STM32G0
+  volatile uint32_t *src;
+
+  src = (uint32_t *)(STM32_USBRAM_BASE + (uint32_t)pma);
+  while (nbytes > 0)
+    {
+      uint32_t value = *src++;
+      uint16_t count = nbytes > 4 ? 4 : nbytes;
+      uint16_t i;
+
+      for (i = 0; i < count; i++)
+        {
+          *buffer++ = (uint8_t)value;
+          value >>= 8;
+        }
+
+      nbytes -= count;
+    }
+#else
   uint16_t *src;
   int     nwords = (nbytes + 1) >> 1;
   int     i;
@@ -1089,6 +1211,7 @@ stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t 
nbytes)
 
       buffer += 2;
     }
+#endif
 }
 
 /****************************************************************************
@@ -3531,7 +3654,9 @@ static void stm32_hwreset(struct stm32_usbdev_s *priv)
 
   /* Set the STM32 BTABLE address */
 
+#ifndef CONFIG_STM32_STM32G0
   stm32_putreg(STM32_BTABLE_ADDRESS & 0xfff8, STM32_USB_BTABLE);
+#endif
 
   /* Initialize EP0 */
 
@@ -3566,6 +3691,12 @@ static void stm32_hwsetup(struct stm32_usbdev_s *priv)
 {
   int epno;
 
+#ifdef CONFIG_STM32_STM32G0
+  /* Enable the STM32G0 USB transceiver supply. */
+
+  stm32_pwr_enableusv(true);
+#endif
+
   /* Power the USB controller, put the USB controller into reset, disable
    * all USB interrupts
    */
@@ -3662,6 +3793,12 @@ static void stm32_hwshutdown(struct stm32_usbdev_s *priv)
   /* Power down the USB controller */
 
   stm32_putreg(USB_CNTR_FRES | USB_CNTR_PDWN, STM32_USB_CNTR);
+
+#ifdef CONFIG_STM32_STM32G0
+  /* Disable the STM32G0 USB transceiver supply. */
+
+  stm32_pwr_enableusv(false);
+#endif
 }
 
 /****************************************************************************
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
index c5455b4df97..144d7cc6f63 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
@@ -74,6 +74,7 @@
 #define STM32_USART4_BASE    0x40004c00     /* 0x40004c00-0x40004fff USART4 */
 #define STM32_I2C1_BASE      0x40005400     /* 0x40005400-0x400057ff I2C1 */
 #define STM32_I2C2_BASE      0x40005800     /* 0x40005800-0x40005bff I2C2 */
+#define STM32_USB_BASE       0x40005c00     /* 0x40005c00-0x40005fff USB */
 #define STM32_CRS_BASE       0x40006C00     /* 0x40006C00-0x40006fff CRS */
 #define STM32_PWR_BASE       0x40007000     /* 0x40007000-0x400073ff PWR */
 #define STM32_DAC1_BASE      0x40007400     /* 0x40007400-0x400077ff DAC 1 */
@@ -81,6 +82,8 @@
 #define STM32_LPTIM1_BASE    0x40007C00     /* 0x40007c00-0x40007fff LPTIM1 */
 #define STM32_LPUART1_BASE   0x40008000     /* 0x40008000-0x400083ff LPUART1 */
 #define STM32_LPTIM2_BASE    0x40009400     /* 0x40009400-0x400097ff LPTIM2 */
+#define STM32_USBRAM_BASE    0x40009800     /* 0x40009800-0x40009bff USB RAM1 
*/
+#define STM32_USBRAM2_BASE   0x40009c00     /* 0x40009c00-0x40009fff USB RAM2 
*/
 #define STM32_UCPD1_BASE     0x4000a000     /* 0x4000a000-0x4000a3ff UCPD1 */
 #define STM32_UCPD2_BASE     0x4000a400     /* 0x4000a400-0x4000a7ff UCPD2 */
 #define STM32_TAMP_BASE      0x4000b000     /* 0x4000b000-0x4000b3ff TAMP */
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
index 3cc3b5b0850..bbd5e79cedd 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
@@ -273,6 +273,11 @@
 #define GPIO_USART4_TX_2    (GPIO_ALT | GPIO_PULLUP | GPIO_AF1 | GPIO_PUSHPULL 
| GPIO_PORTC | GPIO_PIN10)
 #define GPIO_USART4_RTS_1   (GPIO_ALT | GPIO_AF4 | GPIO_PORTA | GPIO_PIN15)
 
+/* USB */
+
+#define GPIO_USB_DM       (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTA | GPIO_PIN11)
+#define GPIO_USB_DP       (GPIO_INPUT | GPIO_FLOAT | GPIO_PORTA | GPIO_PIN12)
+
 /* TODO: LPTIM */
 
 /* TODO: LPUART */
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_pwr.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_pwr.h
index 2df357db170..0e6ec210a40 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_pwr.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_pwr.h
@@ -120,6 +120,7 @@
 #define PWR_CR2_PVDFT_MASK       (7 << PWR_CR2_PLS_SHIFT)
 #define PWR_CR2_PVDRT_SHIFT      (4)      /* Bits 4-6: Power voltage detector 
rising threshold selection */
 #define PWR_CR2_PVDRT_MASK       (7 << PWR_CR2_PLS_SHIFT)
+#define PWR_CR2_USV              (1 << 10) /* Bit 10: USB supply valid */
 
 /* Power control register 3 */
 
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_rcc.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_rcc.h
index 3c5f8ca4521..003a2305754 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_rcc.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_rcc.h
@@ -220,7 +220,8 @@
                                               /* Bits 2-3: Reserved */
 #define RCC_APB1RSTR_TIM6RST        (1 << 4)  /* Bit 4:  Timer 6 reset */
 #define RCC_APB1RSTR_TIM7RST        (1 << 5)  /* Bit 5:  Timer 7 reset */
-                                              /* Bits 6-13: Reserved */
+                                              /* Bits 6-12: Reserved */
+#define RCC_APB1RSTR_USBRST         (1 << 13) /* Bit 13: USB reset */
 #define RCC_APB1RSTR_SPI2RST        (1 << 14) /* Bit 14: SPI 2 reset */
                                               /* Bits 15-16: Reserved */
 #define RCC_APB1RSTR_USART2RST      (1 << 17) /* Bit 17: USART 2 reset */
@@ -284,9 +285,11 @@
                                               /* Bits 2-3: Reserved */
 #define RCC_APB1ENR_TIM6EN          (1 << 4)  /* Bit 4:  Timer 6 enable */
 #define RCC_APB1ENR_TIM7EN          (1 << 5)  /* Bit 5:  Timer 7 enable */
-                                              /* Bits 6-13: Reserved */
+                                              /* Bits 6-12: Reserved */
+#define RCC_APB1ENR_USBEN           (1 << 13) /* Bit 13: USB enable */
 #define RCC_APB1ENR_SPI2EN          (1 << 14) /* Bit 14: SPI 2 enable */
-                                              /* Bits 15-16: Reserved */
+                                              /* Bit 15: Reserved */
+#define RCC_APB1ENR_CRSEN           (1 << 16) /* Bit 16: CRS enable */
 #define RCC_APB1ENR_USART2EN        (1 << 17) /* Bit 17: USART 2 enable */
 #define RCC_APB1ENR_USART3EN        (1 << 18) /* Bit 18: USART 3 enable */
 #define RCC_APB1ENR_USART4EN        (1 << 19) /* Bit 19: USART 4 enable */
diff --git a/arch/arm/src/stm32g0/stm32_rcc.c b/arch/arm/src/stm32g0/stm32_rcc.c
index f2f084012f8..0e9733b9e38 100644
--- a/arch/arm/src/stm32g0/stm32_rcc.c
+++ b/arch/arm/src/stm32g0/stm32_rcc.c
@@ -54,6 +54,12 @@
 #  endif
 #endif
 
+/* HSI48 is the only 48MHz clock source on STM32G0 */
+
+#if defined(CONFIG_STM32_HAVE_HSI48) && defined(STM32_USE_CLK48)
+#  define STM32_USE_HSI48
+#endif
+
 static_assert(CONFIG_BOARD_LOOPSPERMSEC != -1,
               "Configure BOARD_LOOPSPERMSEC to non-default value.");
 
diff --git a/arch/arm/src/stm32g0/stm32g0_rcc.c 
b/arch/arm/src/stm32g0/stm32g0_rcc.c
index b79a0224392..5a90665f868 100644
--- a/arch/arm/src/stm32g0/stm32g0_rcc.c
+++ b/arch/arm/src/stm32g0/stm32g0_rcc.c
@@ -205,6 +205,12 @@ static inline void rcc_enableapb1(void)
   regval |= RCC_APB1ENR_TIM7EN;
 #endif
 
+#ifdef CONFIG_STM32_USB
+  /* USB clock enable */
+
+  regval |= RCC_APB1ENR_USBEN;
+#endif
+
 #ifdef CONFIG_STM32_SPI2
   /* SPI 2 clock enable */
 
@@ -241,6 +247,12 @@ static inline void rcc_enableapb1(void)
   regval |= RCC_APB1ENR_I2C1EN;
 #endif
 
+#if defined(CONFIG_STM32_CRS) || defined(STM32_USE_HSI48)
+  /* Clock recovery system clock enable */
+
+  regval |= RCC_APB1ENR_CRSEN;
+#endif
+
 #ifdef CONFIG_STM32_I2C2
   /* I2C 2 clock enable */
 
@@ -674,6 +686,12 @@ static inline void rcc_enableperipherals(void)
   rcc_enableahb();
   rcc_enableapb2();
   rcc_enableapb1();
+
+#ifdef STM32_USE_HSI48
+  /* Enable HSI48 clocking to support USB transfers or RNG */
+
+  stm32_enable_hsi48(STM32_HSI48_SYNCSRC);
+#endif
 }
 
 /****************************************************************************

Reply via email to