Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions src/machine/machine_stm32_otgfs_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const (

// OTG FS register blocks.
var (
otgDevice = (*usbDeviceRegs)(unsafe.Pointer(stm32.OTG_FS_DEVICE))
otgPower = (*usbPowerRegs)(unsafe.Pointer(stm32.OTG_FS_PWRCLK))
otgDevice = stm32.OTG_FS_DEVICE
otgPower = stm32.OTG_FS_PWRCLK
)

// usbDeviceRegs represents the USB device-mode control block at base+0x800.
Expand Down Expand Up @@ -143,22 +143,22 @@ const (

// GINTSTS / GINTMSK bits (values taken from stm32f405 SVD constants).
const (
gintRXFLVL = uint32(stm32.USB_OTG_FS_GINTSTS_RXFLVL) // 0x10
gintUSBRST = uint32(stm32.USB_OTG_FS_GINTSTS_USBRST) // 0x1000
gintENUMDNE = uint32(stm32.USB_OTG_FS_GINTSTS_ENUMDNE) // 0x2000
gintUSBSUSP = uint32(stm32.USB_OTG_FS_GINTSTS_USBSUSP) // 0x800
gintWKUPINT = uint32(stm32.USB_OTG_FS_GINTSTS_WKUPINT) // 0x80000000
gintIEPINT = uint32(stm32.USB_OTG_FS_GINTSTS_IEPINT) // 0x40000
gintOEPINT = uint32(stm32.USB_OTG_FS_GINTSTS_OEPINT) // 0x80000
gintRXFLVL = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_RXFLVL) // 0x10
gintUSBRST = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_USBRST) // 0x1000
gintENUMDNE = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_ENUMDNE) // 0x2000
gintUSBSUSP = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_USBSUSP) // 0x800
gintWKUPINT = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_WKUPINT) // 0x80000000
gintIEPINT = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_IEPINT) // 0x40000
gintOEPINT = uint32(stm32.USB_OTG_FS_GLOBAL_GINTSTS_OEPINT) // 0x80000
)

// GRSTCTL bits.
const (
grstCSRST = uint32(stm32.USB_OTG_FS_GRSTCTL_CSRST) // core soft reset
grstRXFFLSH = uint32(stm32.USB_OTG_FS_GRSTCTL_RXFFLSH) // RX FIFO flush
grstTXFFLSH = uint32(stm32.USB_OTG_FS_GRSTCTL_TXFFLSH) // TX FIFO flush
grstTXFNUM_Pos = uint32(stm32.USB_OTG_FS_GRSTCTL_TXFNUM_Pos)
grstAHBIDL = uint32(stm32.USB_OTG_FS_GRSTCTL_AHBIDL) // AHB master idle
grstCSRST = uint32(stm32.USB_OTG_FS_GLOBAL_GRSTCTL_CSRST) // core soft reset
grstRXFFLSH = uint32(stm32.USB_OTG_FS_GLOBAL_GRSTCTL_RXFFLSH) // RX FIFO flush
grstTXFFLSH = uint32(stm32.USB_OTG_FS_GLOBAL_GRSTCTL_TXFFLSH) // TX FIFO flush
grstTXFNUM_Pos = uint32(stm32.USB_OTG_FS_GLOBAL_GRSTCTL_TXFNUM_Pos)
grstAHBIDL = uint32(stm32.USB_OTG_FS_GLOBAL_GRSTCTL_AHBIDL) // AHB master idle
)

// FIFO size layout in 32-bit words (total budget = 320 words).
Expand Down Expand Up @@ -236,11 +236,11 @@ func (dev *USBDevice) Configure(config UARTConfig) {
// ---- 4. Force device mode, set turnaround time --------------------------

gusbcfg := stm32.OTG_FS_GLOBAL.GUSBCFG.Get()
gusbcfg &^= stm32.USB_OTG_FS_GUSBCFG_FHMOD |
stm32.USB_OTG_FS_GUSBCFG_FDMOD |
stm32.USB_OTG_FS_GUSBCFG_TRDT_Msk
gusbcfg |= stm32.USB_OTG_FS_GUSBCFG_FDMOD |
(9 << stm32.USB_OTG_FS_GUSBCFG_TRDT_Pos) // turnaround time = 9 for 216MHz HCLK
gusbcfg &^= stm32.USB_OTG_FS_GLOBAL_GUSBCFG_FHMOD |
stm32.USB_OTG_FS_GLOBAL_GUSBCFG_FDMOD |
stm32.USB_OTG_FS_GLOBAL_GUSBCFG_TRDT_Msk
gusbcfg |= stm32.USB_OTG_FS_GLOBAL_GUSBCFG_FDMOD |
(9 << stm32.USB_OTG_FS_GLOBAL_GUSBCFG_TRDT_Pos) // turnaround time = 9 for 216MHz HCLK
stm32.OTG_FS_GLOBAL.GUSBCFG.Set(gusbcfg)

// ---- 5. PHY / VBUS configuration (platform-specific) --------------------
Expand Down Expand Up @@ -301,7 +301,7 @@ func (dev *USBDevice) Configure(config UARTConfig) {
otgDevice.DOEPMSK.Set(depintXFRC | depintSTUP)

// Enable global interrupt
stm32.OTG_FS_GLOBAL.GAHBCFG.SetBits(stm32.USB_OTG_FS_GAHBCFG_GINT)
stm32.OTG_FS_GLOBAL.GAHBCFG.SetBits(stm32.USB_OTG_FS_GLOBAL_GAHBCFG_GINT)

// ---- 11. Register and enable NVIC interrupt -----------------------------

Expand Down Expand Up @@ -405,10 +405,10 @@ func handleRxFIFO() {
for stm32.OTG_FS_GLOBAL.GINTSTS.HasBits(gintRXFLVL) {
status := stm32.OTG_FS_GLOBAL.GRXSTSP_Device.Get()

ep := status & stm32.USB_OTG_FS_GRXSTSP_Device_EPNUM_Msk
bcnt := (status & stm32.USB_OTG_FS_GRXSTSP_Device_BCNT_Msk) >>
stm32.USB_OTG_FS_GRXSTSP_Device_BCNT_Pos
pktsts := (status >> stm32.USB_OTG_FS_GRXSTSP_Device_PKTSTS_Pos) & 0xF
ep := status & stm32.USB_OTG_FS_GLOBAL_GRXSTSP_Device_EPNUM_Msk
bcnt := (status & stm32.USB_OTG_FS_GLOBAL_GRXSTSP_Device_BCNT_Msk) >>
stm32.USB_OTG_FS_GLOBAL_GRXSTSP_Device_BCNT_Pos
pktsts := (status >> stm32.USB_OTG_FS_GLOBAL_GRXSTSP_Device_PKTSTS_Pos) & 0xF

pep := ep // GRXSTSP.EPNUM is already a physical endpoint (0–3)

Expand Down
2 changes: 1 addition & 1 deletion src/machine/machine_stm32f4_otgfs_novbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import "device/stm32"
// GCCFG.PWRDWN deactivates the PHY power-down; NOVBUSSENS skips the VBUS pin
// check so boards without PA9 connected to VBUS still enumerate.
func initOTGFSPHY() {
stm32.OTG_FS_GLOBAL.GCCFG.Set(stm32.USB_OTG_FS_GCCFG_PWRDWN)
stm32.OTG_FS_GLOBAL.GCCFG.Set(stm32.USB_OTG_FS_GLOBAL_GCCFG_PWRDWN)
}
4 changes: 2 additions & 2 deletions src/machine/machine_stm32f4_otgfs_vbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import "device/stm32"
// check so boards without PA9 connected to VBUS still enumerate.
func initOTGFSPHY() {
stm32.OTG_FS_GLOBAL.GCCFG.Set(
stm32.USB_OTG_FS_GCCFG_PWRDWN | // enable FS PHY
stm32.USB_OTG_FS_GCCFG_NOVBUSSENS, // bypass VBUS sensing
stm32.USB_OTG_FS_GLOBAL_GCCFG_PWRDWN | // enable FS PHY
stm32.USB_OTG_FS_GLOBAL_GCCFG_NOVBUSSENS, // bypass VBUS sensing
)
}
8 changes: 4 additions & 4 deletions src/machine/machine_stm32f7_otgfs_vbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ func initOTGFSPHY() {
}

// Enable FS PHY.
stm32.OTG_FS_GLOBAL.GCCFG.SetBits(stm32.USB_OTG_FS_GCCFG_PWRDWN)
stm32.OTG_FS_GLOBAL.GCCFG.SetBits(stm32.USB_OTG_FS_GLOBAL_GCCFG_PWRDWN)

// Disable hardware VBUS detection (F7 uses VBDEN, opposite polarity to F4's NOVBUSSENS).
// Clearing this prevents the peripheral from gating enumeration on PA9 VBUS level.
stm32.OTG_FS_GLOBAL.GCCFG.ClearBits(stm32.USB_OTG_FS_GCCFG_VBDEN)
stm32.OTG_FS_GLOBAL.GCCFG.ClearBits(stm32.USB_OTG_FS_GLOBAL_GCCFG_VBDEN)

// Override B-session valid so GOTGCTL-based detection reports device connected.
stm32.OTG_FS_GLOBAL.GOTGCTL.SetBits(
stm32.USB_OTG_FS_GOTGCTL_BVALOEN | // enable B-valid override
stm32.USB_OTG_FS_GOTGCTL_BVALOVAL, // set B-valid = 1
stm32.USB_OTG_FS_GLOBAL_GOTGCTL_BVALOEN | // enable B-valid override
stm32.USB_OTG_FS_GLOBAL_GOTGCTL_BVALOVAL, // set B-valid = 1
)
}
76 changes: 54 additions & 22 deletions tools/gen-device-svd/gen-device-svd.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ type SVDField struct {
}

type SVDCluster struct {
Dim *int `xml:"dim"`
Dim *string `xml:"dim"`
DimIncrement string `xml:"dimIncrement"`
DimIndex *string `xml:"dimIndex"`
Name string `xml:"name"`
Expand Down Expand Up @@ -231,13 +231,8 @@ func processSubCluster(p *Peripheral, cluster *SVDCluster, clusterOffset uint64,
if err != nil {
panic(err)
}
subdim := *subClusterEl.Dim
subdimIncrement, err := strconv.ParseInt(subClusterEl.DimIncrement, 0, 32)
if err != nil {
panic(err)
}

if subdim > 1 {
subDA := decodeDimArray(subClusterEl.Dim, subClusterEl.DimIndex, subClusterEl.DimIncrement, "subCluster", subclusterName)
if subDA != nil && subDA.dim > 1 {
subcpRegisters := []*PeripheralField{}
for _, regEl := range subClusterEl.Registers {
subcpRegisters = append(subcpRegisters, parseRegister(p.GroupName, regEl, p.BaseAddress+clusterOffset+subclusterOffset, subclusterPrefix)...)
Expand All @@ -248,8 +243,8 @@ func processSubCluster(p *Peripheral, cluster *SVDCluster, clusterOffset uint64,
Address: p.BaseAddress + clusterOffset + subclusterOffset,
Description: subClusterEl.Description,
Registers: subcpRegisters,
Array: subdim,
ElementSize: int(subdimIncrement),
Array: subDA.dim,
ElementSize: int(subDA.incr),
ShortName: clusterPrefix + subclusterName,
})
} else {
Expand Down Expand Up @@ -277,37 +272,71 @@ func processSubCluster(p *Peripheral, cluster *SVDCluster, clusterOffset uint64,
return peripheralsList
}

func (cluster *SVDCluster) name() string {
clusterName := strings.ReplaceAll(cluster.Name, "[%s]", "")
if cluster.DimIndex != nil {
clusterName = strings.ReplaceAll(clusterName, "%s", "")
}
return clusterName
}

func processCluster(p *Peripheral, clusters []*SVDCluster, peripheralDict map[string]*Peripheral) []*Peripheral {
var peripheralsList []*Peripheral
for _, cluster := range clusters {
clusterName := strings.ReplaceAll(cluster.Name, "[%s]", "")
if cluster.DimIndex != nil {
clusterName = strings.ReplaceAll(clusterName, "%s", "")
skipNext := false
for i, cluster := range clusters {
if skipNext {
skipNext = false
continue
}
clusterName := cluster.name()
clusterPrefix := clusterName + "_"
clusterOffset, err := strconv.ParseUint(cluster.AddressOffset, 0, 32)
if err != nil {
panic(err)
}
var dim, dimIncrement int
if cluster.Dim == nil {
da := decodeDimArray(cluster.Dim, cluster.DimIndex, cluster.DimIncrement, "cluster", clusterName)
if da == nil {
// Nordic SVD have sub-clusters with another sub-clusters.
if clusterOffset == 0 || len(cluster.Clusters) > 0 {
peripheralsList = append(peripheralsList, processSubCluster(p, cluster, clusterOffset, clusterName, peripheralDict)...)
continue
}
dim = -1
dimIncrement = -1
if i+1 < len(clusters) {
// If the next cluster is an array and has a name matching
// the current cluster's name, like DIEP%s matches DIEP0,
// and if it is directly adjacent to the current cluster,
// merge the next cluster into the current one consistently.
// This avoids having types like ..DEVICE_DIEP0_Type and
// ..DEVICE_DIEP_Type at the same time, also
next := clusters[i+1]
nextClusterName := next.name()
if strings.HasPrefix(clusterName, nextClusterName) {
if nextDA := decodeDimArray(next.Dim, next.DimIndex, next.DimIncrement, "cluster", nextClusterName); nextDA != nil {
nextClusterOffset, err := strconv.ParseUint(next.AddressOffset, 0, 32)
if err != nil {
panic(err)
}
// Test if current and next clusters are adjacent.
if uint32(nextClusterOffset-clusterOffset) == nextDA.incr {
// merge
skipNext = true
dim = 1 + nextDA.dim
dimIncrement = int(nextDA.incr)
clusterName = nextClusterName
clusterPrefix = clusterName + "_"
}
}
}
}
} else {
dim = *cluster.Dim
dim = da.dim
if dim == 1 {
dimIncrement = -1
} else {
inc, err := strconv.ParseUint(cluster.DimIncrement, 0, 32)
if err != nil {
panic(err)
}
dimIncrement = int(inc)
dimIncrement = int(da.incr)
}
}
clusterRegisters := []*PeripheralField{}
Expand All @@ -325,7 +354,9 @@ func processCluster(p *Peripheral, clusters []*SVDCluster, peripheralDict map[st
lastReg := clusterRegisters[len(clusterRegisters)-1]
lastAddress := lastReg.Address
if lastReg.Array != -1 {
lastAddress = lastReg.Address + uint64(lastReg.Array*lastReg.ElementSize)
lastAddress += uint64(lastReg.Array * lastReg.ElementSize)
} else {
lastAddress += uint64(lastReg.ElementSize)
}
firstAddress := clusterRegisters[0].Address
dimIncrement = int(lastAddress - firstAddress)
Expand Down Expand Up @@ -390,6 +421,7 @@ func readSVD(path, sourceURL string) (*Device, error) {
if groupName == "" {
groupName = cleanName(periphEl.Name)
}
groupName = tweakPeriphGroup(periphEl, groupName)

for _, interrupt := range periphEl.Interrupts {
addInterrupt(interrupts, interrupt.Name, interrupt.Name, interrupt.Index, description)
Expand Down
33 changes: 33 additions & 0 deletions tools/gen-device-svd/tweak.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,39 @@ import (
"strings"
)

func tweakPeriphGroup(p *SVDPeripheral, groupName string) string {
groupName, _ = tweakUSBOTGGroupName(p.Name, groupName)
return groupName
}

// Some peripherals, like OTG_{FS,HS}_{DEVICE,HOST,GLOBAL}
// share the same group name USB_OTG_{FS,HS}.
// Since currently the group name decides about the name of the
// peripheral type declaration (which is reasonable for peripherals
// like TIMn), in case of the OTG peripherals it results in only
// one of the peripherals being present in the device .go file,
// the other definitions get ignored, as they are wrongly recognized
// as identical definitions, which they are not.
// To avoid this behaviour, tweakUSBOTGroupName adjusts the group name
// in these cases.
func tweakUSBOTGGroupName(periphName, groupName string) (string, bool) {
speed, found := strings.CutPrefix(groupName, "USB_OTG_")
if !found {
return groupName, false
}
// speed normally is one of "FS" or "HS"
if !strings.HasPrefix(periphName, "OTG") {
return groupName, false
}
speedPart := "_" + speed + "_"
i := strings.Index(periphName, speedPart)
if i == -1 {
return groupName, false
}
return groupName + periphName[i+len(speedPart)-1:], true

}

func tweakDevice(d *Device, pkgName string) {
if pkgName != "stm32" {
// no-op for device types that do not need tweaks
Expand Down
Loading