diff --git a/src/machine/machine_stm32_otgfs_usb.go b/src/machine/machine_stm32_otgfs_usb.go index 47f70936d5..e8ed3f89ed 100644 --- a/src/machine/machine_stm32_otgfs_usb.go +++ b/src/machine/machine_stm32_otgfs_usb.go @@ -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. @@ -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). @@ -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) -------------------- @@ -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 ----------------------------- @@ -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) diff --git a/src/machine/machine_stm32f4_otgfs_novbus.go b/src/machine/machine_stm32f4_otgfs_novbus.go index 19b35d5e3e..aa046bd6b1 100644 --- a/src/machine/machine_stm32f4_otgfs_novbus.go +++ b/src/machine/machine_stm32f4_otgfs_novbus.go @@ -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) } diff --git a/src/machine/machine_stm32f4_otgfs_vbus.go b/src/machine/machine_stm32f4_otgfs_vbus.go index e9830d9969..bb66505959 100644 --- a/src/machine/machine_stm32f4_otgfs_vbus.go +++ b/src/machine/machine_stm32f4_otgfs_vbus.go @@ -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 ) } diff --git a/src/machine/machine_stm32f7_otgfs_vbus.go b/src/machine/machine_stm32f7_otgfs_vbus.go index 97638084c2..6df6bd5faf 100644 --- a/src/machine/machine_stm32f7_otgfs_vbus.go +++ b/src/machine/machine_stm32f7_otgfs_vbus.go @@ -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 ) } diff --git a/tools/gen-device-svd/gen-device-svd.go b/tools/gen-device-svd/gen-device-svd.go index ef9dedff97..227b6fd10b 100755 --- a/tools/gen-device-svd/gen-device-svd.go +++ b/tools/gen-device-svd/gen-device-svd.go @@ -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"` @@ -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)...) @@ -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 { @@ -277,20 +272,31 @@ 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)...) @@ -298,16 +304,39 @@ func processCluster(p *Peripheral, clusters []*SVDCluster, peripheralDict map[st } 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{} @@ -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) @@ -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) diff --git a/tools/gen-device-svd/tweak.go b/tools/gen-device-svd/tweak.go index 8ee505da14..d55f5e8883 100644 --- a/tools/gen-device-svd/tweak.go +++ b/tools/gen-device-svd/tweak.go @@ -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