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
}
/****************************************************************************