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 <jsanchez@2g-eng.com>
This commit is contained in:
jsanchez-2g
2026-08-22 11:09:08 +08:00
committed by Xiang Xiao
parent 53d757f081
commit 4ebc8a7291
11 changed files with 314 additions and 50 deletions
+1
View File
@@ -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 */
@@ -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) */
/* Buffer Descriptor Table (Relative 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) */
#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 */
+19
View File
@@ -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
*
@@ -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 */
File diff suppressed because it is too large Load Diff
@@ -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 */
@@ -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 */
@@ -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 */
+6 -3
View File
@@ -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 */
+6
View File
@@ -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.");
+18
View File
@@ -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
}
/****************************************************************************