From 771b49f1e5cfc1594aa82f6dff30155b87e04cd8 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 19 Nov 2025 00:36:39 +0100 Subject: [PATCH 01/62] WIP --- .gitmodules | 3 +++ lib/py32-svd | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/py32-svd diff --git a/.gitmodules b/.gitmodules index 5b780d67ad..8568346a95 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,3 +41,6 @@ [submodule "lib/bdwgc"] path = lib/bdwgc url = https://github.com/ivmai/bdwgc.git +[submodule "lib/py32-svd"] + path = lib/py32-svd + url = https://github.com/burgrp/py32-svd.git diff --git a/lib/py32-svd b/lib/py32-svd new file mode 160000 index 0000000000..d98c758f53 --- /dev/null +++ b/lib/py32-svd @@ -0,0 +1 @@ +Subproject commit d98c758f530cfa61e607334b50e19f6c113f8d1d From 94707e6f352aa48d1cba824c53cbafd85166cae1 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 19 Nov 2025 00:36:48 +0100 Subject: [PATCH 02/62] WIP --- .gitignore | 2 ++ make/gen-device.mk | 8 ++++++-- src/runtime/runtime_py32.go | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/runtime/runtime_py32.go diff --git a/.gitignore b/.gitignore index 2761d1fcc7..0b03c83ead 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ src/device/renesas/*.go src/device/renesas/*.s src/device/rp/*.go src/device/rp/*.s +src/device/py32/*.go +src/device/py32/*.s ./vendor llvm-build llvm-project diff --git a/make/gen-device.mk b/make/gen-device.mk index 25845fc5a0..8a777e4d5e 100644 --- a/make/gen-device.mk +++ b/make/gen-device.mk @@ -2,9 +2,9 @@ .PHONY: gen-device gen-device-avr gen-device-esp gen-device-nrf gen-device-sam \ gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp \ - gen-device-stm32 gen-device-renesas + gen-device-stm32 gen-device-renesas gen-device-py32 -gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources +gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp gen-device-py32 ## Generate microcontroller-specific sources ifneq ($(RENESAS), 0) gen-device: gen-device-renesas endif @@ -58,3 +58,7 @@ gen-device-rp: build/gen-device-svd gen-device-renesas: build/gen-device-svd ./build/gen-device-svd -source=https://github.com/cmsis-svd/cmsis-svd-data/tree/master/data/Renesas lib/cmsis-svd/data/Renesas/ src/device/renesas/ GO111MODULE=off $(GO) fmt ./src/device/renesas + +gen-device-py32: build/gen-device-svd + ./build/gen-device-svd -source=https://github.com/tinygo-org/py32-svd lib/py32-svd/svd src/device/py32/ + GO111MODULE=off $(GO) fmt ./src/device/py32 diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go new file mode 100644 index 0000000000..72c5029f2a --- /dev/null +++ b/src/runtime/runtime_py32.go @@ -0,0 +1,19 @@ +//go:build py32 + +package runtime + +func ticksToNanoseconds(ticks timeUnit) int64 { + return 0 +} + +func nanosecondsToTicks(ns int64) timeUnit { + return 0 +} + +//go:linkname ticks runtime.ticks +func ticks() timeUnit { + return 0 +} + +func sleepTicks(d timeUnit) { +} From a455c6b598e51ac24c1b3cf907877c041ec3c209 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 21 Nov 2025 23:35:27 +0100 Subject: [PATCH 03/62] WIP --- src/runtime/runtime_py32.go | 13 +++++++++++++ targets/py32.json | 10 ++++++++++ targets/py32f002a.json | 12 ++++++++++++ targets/py32f002a.ld | 10 ++++++++++ 4 files changed, 45 insertions(+) create mode 100644 targets/py32.json create mode 100644 targets/py32f002a.json create mode 100644 targets/py32f002a.ld diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 72c5029f2a..e5bdee94b7 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -2,6 +2,16 @@ package runtime +//export Reset_Handler +func main() { + // initSystem() + // arm.Asm("CPSIE i") + // initInternal() + + run() + exit(0) +} + func ticksToNanoseconds(ticks timeUnit) int64 { return 0 } @@ -17,3 +27,6 @@ func ticks() timeUnit { func sleepTicks(d timeUnit) { } + +func putchar(c byte) { +} diff --git a/targets/py32.json b/targets/py32.json new file mode 100644 index 0000000000..6424ef633a --- /dev/null +++ b/targets/py32.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "cortex-m0plus" + ], + "scheduler": "none", + "gc": "none", + "build-tags": [ + "py32" + ] +} \ No newline at end of file diff --git a/targets/py32f002a.json b/targets/py32f002a.json new file mode 100644 index 0000000000..f1ce0b7b65 --- /dev/null +++ b/targets/py32f002a.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002axx" + ], + "linkerscript": "targets/py32f002a.ld", + "extra-files": [ + "src/device/py32/py32f002axx.s" + ] +} \ No newline at end of file diff --git a/targets/py32f002a.ld b/targets/py32f002a.ld new file mode 100644 index 0000000000..3ed1dc12d0 --- /dev/null +++ b/targets/py32f002a.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 20K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 3K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" \ No newline at end of file From 960680a3cb7f5a6a5fb120883c29525a9dcfced8 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 22 Nov 2025 00:01:14 +0100 Subject: [PATCH 04/62] WIP --- src/runtime/runtime_cortexm_hardfault.go | 2 +- src/runtime/runtime_cortexm_hardfault_debug.go | 2 +- src/runtime/runtime_py32.go | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime_cortexm_hardfault.go b/src/runtime/runtime_cortexm_hardfault.go index a1cfc2c3d6..fc59df420d 100644 --- a/src/runtime/runtime_cortexm_hardfault.go +++ b/src/runtime/runtime_cortexm_hardfault.go @@ -1,4 +1,4 @@ -//go:build atsamd21 || nrf51 +//go:build atsamd21 || nrf51 || py32 package runtime diff --git a/src/runtime/runtime_cortexm_hardfault_debug.go b/src/runtime/runtime_cortexm_hardfault_debug.go index 14ab16b35c..80100e12a3 100644 --- a/src/runtime/runtime_cortexm_hardfault_debug.go +++ b/src/runtime/runtime_cortexm_hardfault_debug.go @@ -1,4 +1,4 @@ -//go:build cortexm && !atsamd21 && !nrf51 +//go:build cortexm && !atsamd21 && !nrf51 && !py32 package runtime diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index e5bdee94b7..943f2a7e62 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -2,6 +2,8 @@ package runtime +import "device/py32" + //export Reset_Handler func main() { // initSystem() @@ -29,4 +31,6 @@ func sleepTicks(d timeUnit) { } func putchar(c byte) { + // jenom aby tady něco bylo + py32.GPIOA.SetMODER_MODE0(py32.GPIO_MODER_MODE0_Output) } From 6a194f4848357a4ba8c686a6e0f28a3e6189360b Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 28 Nov 2025 21:06:53 +0100 Subject: [PATCH 05/62] WIP --- src/runtime/runtime_py32.go | 12 +++- targets/embedfire-py32f002b.json | 74 ++++++++++++++++++++++ targets/{py32f002a.json => py32f002b.json} | 4 +- targets/{py32f002a.ld => py32f002b.ld} | 0 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 targets/embedfire-py32f002b.json rename targets/{py32f002a.json => py32f002b.json} (67%) rename targets/{py32f002a.ld => py32f002b.ld} (100%) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 943f2a7e62..5e6011c698 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -2,7 +2,9 @@ package runtime -import "device/py32" +import ( + "device/py32" +) //export Reset_Handler func main() { @@ -10,8 +12,12 @@ func main() { // arm.Asm("CPSIE i") // initInternal() - run() - exit(0) + for { + putchar('A') + } + + // run() + // exit(0) } func ticksToNanoseconds(ticks timeUnit) int64 { diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json new file mode 100644 index 0000000000..9f513050c4 --- /dev/null +++ b/targets/embedfire-py32f002b.json @@ -0,0 +1,74 @@ +{ + "inherits": ["py32f002b"], + "flash-command": "pyocd load -t py32f002bx5 {bin}" +} + +/* + +https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f002b" + +# dimensions counted in pins +width: 8 +height: 11 + + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://i.ibb.co/5X0J6D3Y/fg.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + back: + src: "https://i.ibb.co/ycSZp21x/bg.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "5V:power" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "KEY2:button", "PA0:gpio" ] + - [ "LED2:led", "PA1:gpio" ] + - [ "SWCLK:prog", "PA2:gpio" ] + - [ "KEY1:button", "PA3:gpio" ] + - [ "LED4:led", "PA4:gpio"] + - [ "RESET:button", "PC0:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "PB5:gpio" ] + - [ "PB4:gpio" ] + - [ "PB3:gpio" ] + - [ "SWDIO:prog", "PB6:gpio" ] + - [ "PB7:gpio" ] + - [ "PC1:gpio" ] + - [ "LED3:led", "PA5:gpio" ] + - [ "PA7:gpio"] + - [ "PA6:gpio"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' + + +*/ \ No newline at end of file diff --git a/targets/py32f002a.json b/targets/py32f002b.json similarity index 67% rename from targets/py32f002a.json rename to targets/py32f002b.json index f1ce0b7b65..7630f5dc89 100644 --- a/targets/py32f002a.json +++ b/targets/py32f002b.json @@ -3,9 +3,9 @@ "py32" ], "build-tags": [ - "py32f002axx" + "py32f002bxx" ], - "linkerscript": "targets/py32f002a.ld", + "linkerscript": "targets/py32f002b.ld", "extra-files": [ "src/device/py32/py32f002axx.s" ] diff --git a/targets/py32f002a.ld b/targets/py32f002b.ld similarity index 100% rename from targets/py32f002a.ld rename to targets/py32f002b.ld From 316dcc2e431f6dc31dd92a61fe5f657ce2b91a17 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 29 Nov 2025 19:51:22 +0100 Subject: [PATCH 06/62] WIP --- src/machine/board_embedfire_py32f002b copy.go | 20 +++ src/machine/board_embedfire_py32f002b.go | 20 +++ src/machine/machine_py32.go | 155 ++++++++++++++++++ src/runtime/runtime_py32.go | 13 +- targets/embedfire-py32f002b.json | 8 +- targets/embedfire-py32f030.json | 86 ++++++++++ targets/py32f030.json | 11 ++ targets/py32f030_64k_8k.json | 9 + targets/py32f030_64k_8k.ld | 10 ++ 9 files changed, 318 insertions(+), 14 deletions(-) create mode 100644 src/machine/board_embedfire_py32f002b copy.go create mode 100644 src/machine/board_embedfire_py32f002b.go create mode 100644 src/machine/machine_py32.go create mode 100644 targets/embedfire-py32f030.json create mode 100644 targets/py32f030.json create mode 100644 targets/py32f030_64k_8k.json create mode 100644 targets/py32f030_64k_8k.ld diff --git a/src/machine/board_embedfire_py32f002b copy.go b/src/machine/board_embedfire_py32f002b copy.go new file mode 100644 index 0000000000..b2980b092b --- /dev/null +++ b/src/machine/board_embedfire_py32f002b copy.go @@ -0,0 +1,20 @@ +//go:build embedfire_py32f002b + +// Pin mappings for the Embedfire PY32F002B board. +// Only LED and button aliases are provided. + +package machine + +// LEDs +const ( + LED2 = PA1 + LED3 = PA5 + LED4 = PA4 + LED = LED2 +) + +// Buttons +const ( + KEY1 = PA3 + KEY2 = PA0 +) diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go new file mode 100644 index 0000000000..e628238930 --- /dev/null +++ b/src/machine/board_embedfire_py32f002b.go @@ -0,0 +1,20 @@ +//go:build embedfire_py32f030 + +// Pin mappings for the Embedfire PY32F030 board. +// Only LED and button aliases are provided. + +package machine + +// LEDs +const ( + LED2 = PA2 + LED3 = PA3 + LED4 = PA4 + LED = LED2 +) + +// Buttons +const ( + KEY1 = PA5 + KEY2 = PA6 +) diff --git a/src/machine/machine_py32.go b/src/machine/machine_py32.go new file mode 100644 index 0000000000..5aa1f6be6b --- /dev/null +++ b/src/machine/machine_py32.go @@ -0,0 +1,155 @@ +//go:build py32 + +package machine + +import ( + "device/py32" + "unsafe" +) + +const deviceName = py32.Device + +// Peripheral port offsets. Keep the same spacing used on other MCUs so helpers +// like Pin.getPort can keep using simple division by 16 even though PY32 ports +// only expose 8 pins each. +const ( + portA Pin = iota * 16 + portB + portC +) + +// Port A pins. +const ( + PA0 Pin = portA + iota + PA1 + PA2 + PA3 + PA4 + PA5 + PA6 + PA7 +) + +// Port B pins. +const ( + PB0 Pin = portB + iota + PB1 + PB2 + PB3 + PB4 + PB5 + PB6 + PB7 +) + +// Port C pins. +const ( + PC0 Pin = portC + iota + PC1 + PC2 + PC3 + PC4 + PC5 + PC6 + PC7 +) + +// PinMode values specific to PY32: only GPIO direction and pull configuration. +const ( + PinOutput PinMode = iota + PinInputFloating + PinInputPulldown + PinInputPullup + PinInputAnalog +) +const PinInput PinMode = PinInputFloating + +// Internal helpers for GPIO configuration. +const ( + gpioModeInput = 0 + gpioModeOutput = 1 + gpioModeAnalog = 3 + gpioModeMask = 0x3 + + gpioPullFloating = 0 + gpioPullUp = 1 + gpioPullDown = 2 + gpioPullMask = 0x3 + + gpioOutputSpeedHigh = 2 + gpioOutputSpeedMask = 0x3 +) + +// // CPUFrequency returns the core clock frequency. +// func CPUFrequency() uint32 { +// return 48_000_000 +// } + +func (p Pin) getPortNumber() uint8 { + return uint8(p) >> 4 + +} + +func (p Pin) getPinNumber() uint8 { + return uint8(p) & 0x0F +} + +func (p Pin) getPort() (*py32.GPIO_Type, uint8) { + offset := uintptr(p.getPortNumber()) * (uintptr(unsafe.Pointer(py32.GPIOB)) - uintptr(unsafe.Pointer(py32.GPIOA))) + return (*py32.GPIO_Type)(unsafe.Pointer(uintptr(unsafe.Pointer(py32.GPIOA)) + offset)), p.getPinNumber() +} + +func (p Pin) Set(high bool) { + port, pin := p.getPort() + if high { + port.BSRR.Set(1 << pin) + } else { + port.BSRR.Set(1 << (pin + 16)) + } +} + +func (p Pin) Get() bool { + port, pin := p.getPort() + val := port.IDR.Get() & (1 << pin) + return val > 0 +} + +func (p Pin) Configure(config PinConfig) { + p.enableClock() + port, pin := p.getPort() + pos := (pin % 16) * 2 + + switch config.Mode { + + case PinInputFloating: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + case PinInputPulldown: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos) + case PinInputPullup: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) + case PinOutput: + port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos) + port.OTYPER.ReplaceBits(py32.GPIO_OTYPER_OT0_PushPull, py32.GPIO_OTYPER_OT0_Msk, pos>>1) + port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + case PinInputAnalog: + port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + } +} + +func (p Pin) SetAltFunc(af uint8) { + port, pin := p.getPort() + if pin >= 8 { + port.AFRH.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } else { + port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } +} + +func (p Pin) enableClock() { + portNo := p.getPortNumber() + py32.RCC.IOPENR.SetBits(1 << portNo) +} diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 5e6011c698..16c6eb5ce7 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -8,16 +8,9 @@ import ( //export Reset_Handler func main() { - // initSystem() - // arm.Asm("CPSIE i") - // initInternal() - - for { - putchar('A') - } - - // run() - // exit(0) + preinit() + run() + exit(0) } func ticksToNanoseconds(ticks timeUnit) int64 { diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index 9f513050c4..b3d339bc79 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -1,6 +1,7 @@ { "inherits": ["py32f002b"], - "flash-command": "pyocd load -t py32f002bx5 {bin}" + "flash-command": "pyocd load -t py32f002bx5 {bin}", + "build-tags": ["embedfire_py32f002b"] } /* @@ -13,17 +14,16 @@ title: "embedfire-py32f002b" width: 8 height: 11 - # images can be URLs, use adjustments to fit the pins image: front: - src: "https://i.ibb.co/5X0J6D3Y/fg.png" + src: "https://img.sanishtech.com/u/8f427259002707501b471ef06a77134c.png" top: -450 left: -90 right: -90 bottom: -450 back: - src: "https://i.ibb.co/ycSZp21x/bg.png" + src: "https://img.sanishtech.com/u/3650f247f0b77ef5efbcfca3d75f29aa.png" top: -450 left: -90 right: -90 diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json new file mode 100644 index 0000000000..b198c38c95 --- /dev/null +++ b/targets/embedfire-py32f030.json @@ -0,0 +1,86 @@ +{ + "inherits": ["py32f030_64k_8k"], + "flash-command": "pyocd load -t py32f003x8 {bin}", + "build-tags": ["embedfire_py32f030"] +} + +/* + +https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f030" + +# dimensions counted in pins +width: 8 +height: 16 + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://img.sanishtech.com/u/d7efa5b8e309a987d89bf3f031a4b5e3.png" + top: -520 + left: -120 + right: -120 + bottom: -470 + back: + src: "https://img.sanishtech.com/u/cfc8cd0828646e3bde5c1364fca33458.png" + top: -450 + left: -100 + right: -120 + bottom: -470 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "3V3:power" ] + - [ "PA12:gpio" ] + - [ "SWDIO:prog", "PA13:gpio" ] + - [ "SWCLK:prog", "PA14:gpio" ] + - [ "PA11:gpio" ] + - [ "PA15:gpio" ] + - [ "PB3:gpio" ] + - [ "PB4:gpio" ] + - [ "PB5:gpio"] + - [ "PB6:gpio"] + - [ "PB7:gpio"] + - [ "BOOT0:config", "PF4:gpio"] + - [ "PB8:gpio"] + - [ "PF3:gpio"] + - [ "RESET:button", "PF2:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "5V:power" ] + - [ "PA8:gpio" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "PA7:gpio" ] + - [ "KEY2:button", "PA6:gpio" ] + - [ "KEY1:button", "PA5:gpio"] + - [ "LED4:led", "PA4:gpio"] + - [ "LED3:led", "PA3:gpio"] + - [ "LED2:led", "PA2:gpio"] + - [ "PA1:gpio"] + - [ "PA0:gpio"] + - [ "GND:gnd"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' + config: + label: 'Config' + bgcolor: '#A060FF' + +*/ \ No newline at end of file diff --git a/targets/py32f030.json b/targets/py32f030.json new file mode 100644 index 0000000000..e1bc19bed0 --- /dev/null +++ b/targets/py32f030.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f030", "py32f030xx" + ], + "extra-files": [ + "src/device/py32/py32f030xx.s" + ] +} \ No newline at end of file diff --git a/targets/py32f030_64k_8k.json b/targets/py32f030_64k_8k.json new file mode 100644 index 0000000000..6a248733d8 --- /dev/null +++ b/targets/py32f030_64k_8k.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030_64k_8k" + ], + "linkerscript": "targets/py32f030_64k_8k.ld" +} \ No newline at end of file diff --git a/targets/py32f030_64k_8k.ld b/targets/py32f030_64k_8k.ld new file mode 100644 index 0000000000..380a4d3811 --- /dev/null +++ b/targets/py32f030_64k_8k.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" \ No newline at end of file From 49824dc4d2e9b70a5330f20b368532721d4e5cb3 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 29 Nov 2025 23:15:49 +0100 Subject: [PATCH 07/62] WIP --- .../{machine_py32.go => machine_py32_pin.go} | 39 +++++++++++++++++++ src/machine/machine_py32_systick.go | 30 ++++++++++++++ src/runtime/runtime_py32.go | 21 +++++++--- 3 files changed, 84 insertions(+), 6 deletions(-) rename src/machine/{machine_py32.go => machine_py32_pin.go} (91%) create mode 100644 src/machine/machine_py32_systick.go diff --git a/src/machine/machine_py32.go b/src/machine/machine_py32_pin.go similarity index 91% rename from src/machine/machine_py32.go rename to src/machine/machine_py32_pin.go index 5aa1f6be6b..a135c6a2b2 100644 --- a/src/machine/machine_py32.go +++ b/src/machine/machine_py32_pin.go @@ -16,6 +16,9 @@ const ( portA Pin = iota * 16 portB portC + portD + portE + portF ) // Port A pins. @@ -54,6 +57,42 @@ const ( PC7 ) +// Port D pins. +const ( + PD0 Pin = portD + iota + PD1 + PD2 + PD3 + PD4 + PD5 + PD6 + PD7 +) + +// Port E pins. +const ( + PE0 Pin = portE + iota + PE1 + PE2 + PE3 + PE4 + PE5 + PE6 + PE7 +) + +// Port F pins. +const ( + PF0 Pin = portF + iota + PF1 + PF2 + PF3 + PF4 + PF5 + PF6 + PF7 +) + // PinMode values specific to PY32: only GPIO direction and pull configuration. const ( PinOutput PinMode = iota diff --git a/src/machine/machine_py32_systick.go b/src/machine/machine_py32_systick.go new file mode 100644 index 0000000000..526a514857 --- /dev/null +++ b/src/machine/machine_py32_systick.go @@ -0,0 +1,30 @@ +//go:build py32 + +package machine + +import ( + "device/arm" +) + +var msCounter uint64 + +// CPUFrequency returns the core clock frequency. +func CPUFrequency() uint32 { + return 4_000_000 +} + +func Init() { + LED4.Configure(PinConfig{Mode: PinOutput}) + arm.SetupSystemTimer(CPUFrequency() / 1000) +} + +//export SysTick_Handler +func handleSysTick() { + msCounter = msCounter + 1 + LED4.Set(!LED4.Get()) +} + +// Ticks returns the number of milliseconds since boot. +func GetTicks() uint64 { + return msCounter +} diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 16c6eb5ce7..34e59cd040 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -3,33 +3,42 @@ package runtime import ( - "device/py32" + "device/arm" + "machine" ) //export Reset_Handler func main() { preinit() + machine.Init() run() exit(0) } func ticksToNanoseconds(ticks timeUnit) int64 { - return 0 + return int64(ticks * 1_000_000) } func nanosecondsToTicks(ns int64) timeUnit { - return 0 + return timeUnit(ns / 1_000_000) } //go:linkname ticks runtime.ticks func ticks() timeUnit { - return 0 + return timeUnit(machine.GetTicks()) } func sleepTicks(d timeUnit) { + if d <= 0 { + return + } + start := ticks() + stop := start + d + for ticks() < stop { + arm.Asm("wfe") + } } func putchar(c byte) { - // jenom aby tady něco bylo - py32.GPIOA.SetMODER_MODE0(py32.GPIO_MODER_MODE0_Output) + } From b8d95df652be40a8d1c214c528aeed2e0caaab29 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 00:25:07 +0100 Subject: [PATCH 08/62] WIP --- src/machine/machine_py32_systick.go | 30 --------------------------- src/runtime/runtime_py32.go | 32 +++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 34 deletions(-) delete mode 100644 src/machine/machine_py32_systick.go diff --git a/src/machine/machine_py32_systick.go b/src/machine/machine_py32_systick.go deleted file mode 100644 index 526a514857..0000000000 --- a/src/machine/machine_py32_systick.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build py32 - -package machine - -import ( - "device/arm" -) - -var msCounter uint64 - -// CPUFrequency returns the core clock frequency. -func CPUFrequency() uint32 { - return 4_000_000 -} - -func Init() { - LED4.Configure(PinConfig{Mode: PinOutput}) - arm.SetupSystemTimer(CPUFrequency() / 1000) -} - -//export SysTick_Handler -func handleSysTick() { - msCounter = msCounter + 1 - LED4.Set(!LED4.Get()) -} - -// Ticks returns the number of milliseconds since boot. -func GetTicks() uint64 { - return msCounter -} diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 34e59cd040..b7d43401b1 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -4,28 +4,41 @@ package runtime import ( "device/arm" + "machine" ) //export Reset_Handler func main() { preinit() - machine.Init() + + machine.LED4.Configure(machine.PinConfig{Mode: machine.PinOutput}) + + ConfigureSystemTimer(8e6) + run() exit(0) } +const shift = 15 + +func ConfigureSystemTimer(systemFrequencyHz uint32) { + arm.SetupSystemTimer(systemFrequencyHz / 1000) +} + func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks * 1_000_000) + return int64(ticks * 10_000_000) } func nanosecondsToTicks(ns int64) timeUnit { - return timeUnit(ns / 1_000_000) + return timeUnit(ns / 10_000_000) } +var tickCounter uint64 + //go:linkname ticks runtime.ticks func ticks() timeUnit { - return timeUnit(machine.GetTicks()) + return timeUnit(tickCounter) } func sleepTicks(d timeUnit) { @@ -42,3 +55,14 @@ func sleepTicks(d timeUnit) { func putchar(c byte) { } + +//export SysTick_Handler +func handleSysTick() { + tickCounter = tickCounter + 1 + //machine.LED4.Set(!machine.LED4.Get()) + machine.LED4.High() + for i := 0; i < 100; i++ { + arm.Asm("nop") + } + machine.LED4.Low() +} From 62d35e431f247f4a9b74d28901680a0aa8082816 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 00:29:09 +0100 Subject: [PATCH 09/62] WIP --- src/runtime/runtime_py32.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index b7d43401b1..0e3ccfb639 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -27,11 +27,11 @@ func ConfigureSystemTimer(systemFrequencyHz uint32) { } func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks * 10_000_000) + return int64(ticks * 1_000_000) } func nanosecondsToTicks(ns int64) timeUnit { - return timeUnit(ns / 10_000_000) + return timeUnit(ns / 1_000_000) } var tickCounter uint64 From 353da4f8dd616e023d1e142953fa42a813af82cf Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 00:56:06 +0100 Subject: [PATCH 10/62] WIP --- src/runtime/runtime_py32.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 0e3ccfb639..510295a501 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -6,6 +6,8 @@ import ( "device/arm" "machine" + + "device/py32" ) //export Reset_Handler @@ -14,24 +16,24 @@ func main() { machine.LED4.Configure(machine.PinConfig{Mode: machine.PinOutput}) - ConfigureSystemTimer(8e6) + py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) + + ConfigureSystemTimer(24e6) run() exit(0) } -const shift = 15 - func ConfigureSystemTimer(systemFrequencyHz uint32) { arm.SetupSystemTimer(systemFrequencyHz / 1000) } func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks * 1_000_000) + return int64(ticks * 1000_000) } func nanosecondsToTicks(ns int64) timeUnit { - return timeUnit(ns / 1_000_000) + return timeUnit(ns / 1000_000) } var tickCounter uint64 From 9e7f5e81075c89c8c2f7a65630ee80b3499309a6 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 15:03:11 +0100 Subject: [PATCH 11/62] WIP --- src/runtime/runtime_py32.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 510295a501..0c1c975c1a 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -5,8 +5,6 @@ package runtime import ( "device/arm" - "machine" - "device/py32" ) @@ -14,8 +12,6 @@ import ( func main() { preinit() - machine.LED4.Configure(machine.PinConfig{Mode: machine.PinOutput}) - py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) ConfigureSystemTimer(24e6) @@ -24,6 +20,8 @@ func main() { exit(0) } +// Configure SysTick to fire every 1ms on given system frequency. +// This should be called after any changes to the system clock frequency. func ConfigureSystemTimer(systemFrequencyHz uint32) { arm.SetupSystemTimer(systemFrequencyHz / 1000) } @@ -61,10 +59,4 @@ func putchar(c byte) { //export SysTick_Handler func handleSysTick() { tickCounter = tickCounter + 1 - //machine.LED4.Set(!machine.LED4.Get()) - machine.LED4.High() - for i := 0; i < 100; i++ { - arm.Asm("nop") - } - machine.LED4.Low() } From f435f9ddc973529d4d7bf957ab01cc950686fbd4 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 18:07:08 +0100 Subject: [PATCH 12/62] WIP --- src/runtime/runtime_py32.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 0c1c975c1a..ae647b8493 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -4,6 +4,7 @@ package runtime import ( "device/arm" + "machine" "device/py32" ) @@ -15,6 +16,7 @@ func main() { py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) ConfigureSystemTimer(24e6) + machine.InitSerial() run() exit(0) @@ -53,7 +55,15 @@ func sleepTicks(d timeUnit) { } func putchar(c byte) { + machine.Serial.WriteByte(c) +} +func getchar() byte { + for machine.Serial.Buffered() == 0 { + Gosched() + } + v, _ := machine.Serial.ReadByte() + return v } //export SysTick_Handler From 72560afa1c5e2e8d787721adf60371e583584278 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 20:09:39 +0100 Subject: [PATCH 13/62] WIP --- src/machine/board_embedfire_py32f002b copy.go | 20 ---- src/machine/board_embedfire_py32f002b.go | 20 +++- src/machine/board_embedfire_py32f030.go | 28 +++++ src/machine/machine_py32_pin.go | 57 ++++++++-- src/machine/machine_py32_pin_afrh.go | 12 ++ src/machine/machine_py32_pin_no_afrh.go | 8 ++ src/machine/machine_py32_uart.go | 104 ++++++++++++++++++ src/machine/uart.go | 2 +- src/runtime/runtime_py32.go | 2 +- 9 files changed, 216 insertions(+), 37 deletions(-) delete mode 100644 src/machine/board_embedfire_py32f002b copy.go create mode 100644 src/machine/board_embedfire_py32f030.go create mode 100644 src/machine/machine_py32_pin_afrh.go create mode 100644 src/machine/machine_py32_pin_no_afrh.go create mode 100644 src/machine/machine_py32_uart.go diff --git a/src/machine/board_embedfire_py32f002b copy.go b/src/machine/board_embedfire_py32f002b copy.go deleted file mode 100644 index b2980b092b..0000000000 --- a/src/machine/board_embedfire_py32f002b copy.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build embedfire_py32f002b - -// Pin mappings for the Embedfire PY32F002B board. -// Only LED and button aliases are provided. - -package machine - -// LEDs -const ( - LED2 = PA1 - LED3 = PA5 - LED4 = PA4 - LED = LED2 -) - -// Buttons -const ( - KEY1 = PA3 - KEY2 = PA0 -) diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index e628238930..2d0f501902 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -1,20 +1,28 @@ -//go:build embedfire_py32f030 +//go:build embedfire_py32f002b -// Pin mappings for the Embedfire PY32F030 board. +// Pin mappings for the Embedfire PY32F002B board. // Only LED and button aliases are provided. package machine // LEDs const ( - LED2 = PA2 - LED3 = PA3 + LED2 = PA1 + LED3 = PA5 LED4 = PA4 LED = LED2 ) // Buttons const ( - KEY1 = PA5 - KEY2 = PA6 + KEY1 = PA3 + KEY2 = PA0 +) + +// UART +const ( + DEFAULT_UART_TX_PIN = PA6 + DEFAULT_UART_RX_PIN = PA7 + DEFAULT_UART_TX_PIN_AF = 1 + DEFAULT_UART_RX_PIN_AF = 3 ) diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go new file mode 100644 index 0000000000..d000aef6ca --- /dev/null +++ b/src/machine/board_embedfire_py32f030.go @@ -0,0 +1,28 @@ +//go:build embedfire_py32f030 + +// Pin mappings for the Embedfire PY32F030 board. +// Only LED and button aliases are provided. + +package machine + +// LEDs +const ( + LED2 = PA2 + LED3 = PA3 + LED4 = PA4 + LED = LED2 +) + +// Buttons +const ( + KEY1 = PA5 + KEY2 = PA6 +) + +// UART +const ( + DEFAULT_UART_TX_PIN = PA7 + DEFAULT_UART_RX_PIN = PA8 + DEFAULT_UART_TX_PIN_AF = 8 + DEFAULT_UART_RX_PIN_AF = 8 +) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index a135c6a2b2..2c94c37134 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -31,6 +31,14 @@ const ( PA5 PA6 PA7 + PA8 + PA9 + PA10 + PA11 + PA12 + PA13 + PA14 + PA15 ) // Port B pins. @@ -43,6 +51,14 @@ const ( PB5 PB6 PB7 + PB8 + PB9 + PB10 + PB11 + PB12 + PB13 + PB14 + PB15 ) // Port C pins. @@ -55,6 +71,14 @@ const ( PC5 PC6 PC7 + PC8 + PC9 + PC10 + PC11 + PC12 + PC13 + PC14 + PC15 ) // Port D pins. @@ -67,6 +91,14 @@ const ( PD5 PD6 PD7 + PD8 + PD9 + PD10 + PD11 + PD12 + PD13 + PD14 + PD15 ) // Port E pins. @@ -79,6 +111,14 @@ const ( PE5 PE6 PE7 + PE8 + PE9 + PE10 + PE11 + PE12 + PE13 + PE14 + PE15 ) // Port F pins. @@ -91,6 +131,14 @@ const ( PF5 PF6 PF7 + PF8 + PF9 + PF10 + PF11 + PF12 + PF13 + PF14 + PF15 ) // PinMode values specific to PY32: only GPIO direction and pull configuration. @@ -179,15 +227,6 @@ func (p Pin) Configure(config PinConfig) { } } -func (p Pin) SetAltFunc(af uint8) { - port, pin := p.getPort() - if pin >= 8 { - port.AFRH.ReplaceBits(uint32(af), 0xF, (pin%8)*4) - } else { - port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) - } -} - func (p Pin) enableClock() { portNo := p.getPortNumber() py32.RCC.IOPENR.SetBits(1 << portNo) diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go new file mode 100644 index 0000000000..67c742b513 --- /dev/null +++ b/src/machine/machine_py32_pin_afrh.go @@ -0,0 +1,12 @@ +//go:build py32 && !py32f002bxx + +package machine + +func (p Pin) SetAltFunc(af uint8) { + port, pin := p.getPort() + if pin >= 8 { + port.AFRH.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } else { + port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } +} diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go new file mode 100644 index 0000000000..8b0297a289 --- /dev/null +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -0,0 +1,8 @@ +//go:build py32 && py32f002bxx + +package machine + +func (p Pin) SetAltFunc(af uint8) { + port, pin := p.getPort() + port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) +} diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go new file mode 100644 index 0000000000..8cbe6fc27c --- /dev/null +++ b/src/machine/machine_py32_uart.go @@ -0,0 +1,104 @@ +//go:build py32 + +package machine + +import ( + "device/py32" + "runtime/interrupt" +) + +// Remember the clock used for baud rate calculations so Configure() can be +// called without explicitly passing the clock. +var py32UARTClockHz uint32 = 24_000_000 + +// UART implements a minimal USART1 driver for PY32 parts. +type UART struct { + Bus *py32.USART_Type + Buffer *RingBuffer + irq interrupt.Interrupt +} + +var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer()} + +// ConfigureWithClock initializes the UART using the provided peripheral clock +// frequency (in Hz). This avoids assuming a fixed MCU clock. +func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + // Configure default pins if they weren't provided. + if config.TX == 0 { + ConfigureUARTPin(DEFAULT_UART_TX_PIN, DEFAULT_UART_TX_PIN_AF) + } + + if config.RX == 0 { + ConfigureUARTPin(DEFAULT_UART_RX_PIN, DEFAULT_UART_RX_PIN_AF) + } + + // Enable peripheral clock. + py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) + + // Reset control registers to a known state. + uart.Bus.CR1.Set(0) + uart.Bus.CR2.Set(0) + uart.Bus.CR3.Set(0) + + // Oversampling by 16: BRR expects fck/baud. + divider := (clockHz + (config.BaudRate / 2)) / config.BaudRate + uart.Bus.BRR.Set(divider) + + // Enable transmitter, receiver, RX interrupt, and the peripheral. + uart.Bus.CR1.Set(py32.USART_CR1_TE | py32.USART_CR1_RE | py32.USART_CR1_RXNEIE | py32.USART_CR1_UE) + + // Hook interrupt. + uart.irq = interrupt.New(py32.IRQ_USART1, handleUartInterrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() + + return nil +} + +// Configure uses the last stored clock (defaulting to 24 MHz). Call +// ConfigureWithClock for explicit control. +func (uart *UART) Configure(config UARTConfig) error { + return uart.ConfigureWithClock(config, py32UARTClockHz) +} + +// InitSerialWithClock configures the default Serial using the supplied +// peripheral clock frequency. +func InitSerialWithClock(clockHz uint32) { + py32UARTClockHz = clockHz + //Serial.ConfigureWithClock(UARTConfig{}, clockHz) +} + +// Configure pin for use by UART +func ConfigureUARTPin(pin Pin, af uint8) { + pin.enableClock() + port, n := pin.getPort() + pos := (n % 16) * 2 + + // Alternate function mode is encoded as 0b10. + port.MODER.ReplaceBits(2, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) + port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + pin.SetAltFunc(af) +} + +func handleUartInterrupt(interrupt.Interrupt) { + uart := DefaultUART + data := uint8(uart.Bus.DR.Get()) + uart.Receive(data) +} + +func (uart *UART) writeByte(c byte) error { + for uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { + } + uart.Bus.DR.Set(uint32(c)) + return nil +} + +func (uart *UART) flush() { + for uart.Bus.SR.Get()&py32.USART_SR_TC == 0 { + } +} diff --git a/src/machine/uart.go b/src/machine/uart.go index 32462587b1..e154672e0c 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -1,4 +1,4 @@ -//go:build atmega || esp || nrf || sam || sifive || stm32 || k210 || nxp || rp2040 || rp2350 +//go:build atmega || esp || nrf || sam || sifive || stm32 || k210 || nxp || rp2040 || rp2350 || py32 package machine diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index ae647b8493..5a922ad98b 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -15,7 +15,7 @@ func main() { py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) - ConfigureSystemTimer(24e6) + ConfigureSystemTimer(24_000_000) machine.InitSerial() run() From 77d60b039de61a15f4a39b89bddf47f67139c210 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 21:08:06 +0100 Subject: [PATCH 14/62] WIP --- src/runtime/runtime_py32.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 5a922ad98b..20dbc9dd70 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -50,10 +50,14 @@ func sleepTicks(d timeUnit) { start := ticks() stop := start + d for ticks() < stop { - arm.Asm("wfe") + waitForEvents() } } +func waitForEvents() { + arm.Asm("wfe") +} + func putchar(c byte) { machine.Serial.WriteByte(c) } From ecf2f88deb6c46644a83b7723b3480aa40186964 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 30 Nov 2025 21:27:10 +0100 Subject: [PATCH 15/62] WIP --- src/machine/board_embedfire_py32f002b.go | 6 +++--- src/machine/board_embedfire_py32f030.go | 6 +++--- src/runtime/runtime_py32.go | 10 ++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index 2d0f501902..1877b756d1 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -7,9 +7,9 @@ package machine // LEDs const ( - LED2 = PA1 - LED3 = PA5 - LED4 = PA4 + LED1 = PA1 + LED2 = PA5 + LED3 = PA4 LED = LED2 ) diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go index d000aef6ca..93f5caca5e 100644 --- a/src/machine/board_embedfire_py32f030.go +++ b/src/machine/board_embedfire_py32f030.go @@ -7,9 +7,9 @@ package machine // LEDs const ( - LED2 = PA2 - LED3 = PA3 - LED4 = PA4 + LED1 = PA2 + LED2 = PA3 + LED3 = PA4 LED = LED2 ) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 20dbc9dd70..4088d49b62 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -7,8 +7,12 @@ import ( "machine" "device/py32" + + "runtime/volatile" ) +var tickCounter volatile.Register64 + //export Reset_Handler func main() { preinit() @@ -36,11 +40,9 @@ func nanosecondsToTicks(ns int64) timeUnit { return timeUnit(ns / 1000_000) } -var tickCounter uint64 - //go:linkname ticks runtime.ticks func ticks() timeUnit { - return timeUnit(tickCounter) + return timeUnit(tickCounter.Get()) } func sleepTicks(d timeUnit) { @@ -72,5 +74,5 @@ func getchar() byte { //export SysTick_Handler func handleSysTick() { - tickCounter = tickCounter + 1 + tickCounter.Set(tickCounter.Get() + 1) } From 420bef5805891422db4c4c3818891d5327225070 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 2 Dec 2025 17:01:08 +0100 Subject: [PATCH 16/62] WIP --- src/machine/board_embedfire_py32f002b.go | 1 - src/machine/board_embedfire_py32f030.go | 1 - src/machine/machine_py32_pin.go | 19 +++---------------- src/machine/machine_py32_pin_afrh.go | 2 +- src/machine/machine_py32_pin_no_afrh.go | 2 +- targets/py32f002b.json | 2 +- 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index 1877b756d1..ab5ef80a6f 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -1,7 +1,6 @@ //go:build embedfire_py32f002b // Pin mappings for the Embedfire PY32F002B board. -// Only LED and button aliases are provided. package machine diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go index 93f5caca5e..7d32dab314 100644 --- a/src/machine/board_embedfire_py32f030.go +++ b/src/machine/board_embedfire_py32f030.go @@ -1,7 +1,6 @@ //go:build embedfire_py32f030 // Pin mappings for the Embedfire PY32F030 board. -// Only LED and button aliases are provided. package machine diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 2c94c37134..d244439408 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -9,9 +9,9 @@ import ( const deviceName = py32.Device -// Peripheral port offsets. Keep the same spacing used on other MCUs so helpers -// like Pin.getPort can keep using simple division by 16 even though PY32 ports -// only expose 8 pins each. +// Peripheral port offsets. +// Keep the same spacing used on other MCUs so helpers like Pin.getPortNumber +// can keep using simple division by 16. const ( portA Pin = iota * 16 portB @@ -21,7 +21,6 @@ const ( portF ) -// Port A pins. const ( PA0 Pin = portA + iota PA1 @@ -41,7 +40,6 @@ const ( PA15 ) -// Port B pins. const ( PB0 Pin = portB + iota PB1 @@ -61,7 +59,6 @@ const ( PB15 ) -// Port C pins. const ( PC0 Pin = portC + iota PC1 @@ -81,7 +78,6 @@ const ( PC15 ) -// Port D pins. const ( PD0 Pin = portD + iota PD1 @@ -101,7 +97,6 @@ const ( PD15 ) -// Port E pins. const ( PE0 Pin = portE + iota PE1 @@ -121,7 +116,6 @@ const ( PE15 ) -// Port F pins. const ( PF0 Pin = portF + iota PF1 @@ -141,7 +135,6 @@ const ( PF15 ) -// PinMode values specific to PY32: only GPIO direction and pull configuration. const ( PinOutput PinMode = iota PinInputFloating @@ -151,7 +144,6 @@ const ( ) const PinInput PinMode = PinInputFloating -// Internal helpers for GPIO configuration. const ( gpioModeInput = 0 gpioModeOutput = 1 @@ -167,11 +159,6 @@ const ( gpioOutputSpeedMask = 0x3 ) -// // CPUFrequency returns the core clock frequency. -// func CPUFrequency() uint32 { -// return 48_000_000 -// } - func (p Pin) getPortNumber() uint8 { return uint8(p) >> 4 diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 67c742b513..7077bd4de8 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32f002bxx +//go:build py32 && !no_gpio_afrh package machine diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index 8b0297a289..fb674db8f4 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -1,4 +1,4 @@ -//go:build py32 && py32f002bxx +//go:build py32 && no_gpio_afrh package machine diff --git a/targets/py32f002b.json b/targets/py32f002b.json index 7630f5dc89..2c0c82d8bc 100644 --- a/targets/py32f002b.json +++ b/targets/py32f002b.json @@ -3,7 +3,7 @@ "py32" ], "build-tags": [ - "py32f002bxx" + "py32f002bxx", "no_gpio_afrh" ], "linkerscript": "targets/py32f002b.ld", "extra-files": [ From 871297cb212cd219f1179f8785aa6731580eb60f Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Mon, 15 Dec 2025 20:38:46 +0100 Subject: [PATCH 17/62] PR comments fixed --- lib/bdwgc | 2 +- targets/embedfire-py32f002b-pinout.yaml | 63 +++++++++++++++++ targets/embedfire-py32f002b.json | 81 +++------------------- targets/embedfire-py32f030-pinout.yaml | 76 +++++++++++++++++++++ targets/embedfire-py32f030.json | 91 ++----------------------- targets/py32f002b.json | 3 +- targets/py32f030.json | 3 +- 7 files changed, 159 insertions(+), 160 deletions(-) create mode 100644 targets/embedfire-py32f002b-pinout.yaml create mode 100644 targets/embedfire-py32f030-pinout.yaml diff --git a/lib/bdwgc b/lib/bdwgc index 7577ca7c2d..1166f11f7d 160000 --- a/lib/bdwgc +++ b/lib/bdwgc @@ -1 +1 @@ -Subproject commit 7577ca7c2dc7364bb6733dab23be34231279db6b +Subproject commit 1166f11f7dee08d7ad369296b24cf8c9582f8789 diff --git a/targets/embedfire-py32f002b-pinout.yaml b/targets/embedfire-py32f002b-pinout.yaml new file mode 100644 index 0000000000..44b1b634ab --- /dev/null +++ b/targets/embedfire-py32f002b-pinout.yaml @@ -0,0 +1,63 @@ +# https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f002b" + +# dimensions counted in pins +width: 8 +height: 11 + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://img.sanishtech.com/u/8f427259002707501b471ef06a77134c.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + back: + src: "https://img.sanishtech.com/u/3650f247f0b77ef5efbcfca3d75f29aa.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "5V:power" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "KEY2:button", "PA0:gpio" ] + - [ "LED2:led", "PA1:gpio" ] + - [ "SWCLK:prog", "PA2:gpio" ] + - [ "KEY1:button", "PA3:gpio" ] + - [ "LED4:led", "PA4:gpio"] + - [ "RESET:button", "PC0:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "PB5:gpio" ] + - [ "PB4:gpio" ] + - [ "PB3:gpio" ] + - [ "SWDIO:prog", "PB6:gpio" ] + - [ "PB7:gpio" ] + - [ "PC1:gpio" ] + - [ "LED3:led", "PA5:gpio" ] + - [ "PA7:gpio"] + - [ "PA6:gpio"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index b3d339bc79..b39aa5dc76 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -1,74 +1,9 @@ { - "inherits": ["py32f002b"], - "flash-command": "pyocd load -t py32f002bx5 {bin}", - "build-tags": ["embedfire_py32f002b"] -} - -/* - -https://splitbrain.github.io/pinoutleaf - -title: "embedfire-py32f002b" - -# dimensions counted in pins -width: 8 -height: 11 - -# images can be URLs, use adjustments to fit the pins -image: - front: - src: "https://img.sanishtech.com/u/8f427259002707501b471ef06a77134c.png" - top: -450 - left: -90 - right: -90 - bottom: -450 - back: - src: "https://img.sanishtech.com/u/3650f247f0b77ef5efbcfca3d75f29aa.png" - top: -450 - left: -90 - right: -90 - bottom: -450 - -# Define the pins (label:type), use empty entries when offsets are needed -pins: - left: - - [ "5V:power" ] - - [ "PB2:gpio" ] - - [ "PB1:gpio" ] - - [ "PB0:gpio" ] - - [ "KEY2:button", "PA0:gpio" ] - - [ "LED2:led", "PA1:gpio" ] - - [ "SWCLK:prog", "PA2:gpio" ] - - [ "KEY1:button", "PA3:gpio" ] - - [ "LED4:led", "PA4:gpio"] - - [ "RESET:button", "PC0:gpio"] - - [ "GND:gnd"] - right: - - [ "3V3:power" ] - - [ "PB5:gpio" ] - - [ "PB4:gpio" ] - - [ "PB3:gpio" ] - - [ "SWDIO:prog", "PB6:gpio" ] - - [ "PB7:gpio" ] - - [ "PC1:gpio" ] - - [ "LED3:led", "PA5:gpio" ] - - [ "PA7:gpio"] - - [ "PA6:gpio"] - - [ "GND:gnd"] - -types: - gpio: - label: 'GPIO' - bgcolor: '#00A060' - prog: - label: 'SWD' - bgcolor: '#FFCC00' - led: - label: 'LED' - bgcolor: '#0099FF' - button: - label: 'Button' - bgcolor: '#B0B0B0' - - -*/ \ No newline at end of file + "inherits": [ + "py32f002b" + ], + "flash-command": "pyocd load -t py32f002bx5 {bin}", + "build-tags": [ + "embedfire_py32f002b" + ] +} \ No newline at end of file diff --git a/targets/embedfire-py32f030-pinout.yaml b/targets/embedfire-py32f030-pinout.yaml new file mode 100644 index 0000000000..d117235834 --- /dev/null +++ b/targets/embedfire-py32f030-pinout.yaml @@ -0,0 +1,76 @@ +# https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f030" + +# dimensions counted in pins +width: 8 +height: 16 + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://img.sanishtech.com/u/d7efa5b8e309a987d89bf3f031a4b5e3.png" + top: -520 + left: -120 + right: -120 + bottom: -470 + back: + src: "https://img.sanishtech.com/u/cfc8cd0828646e3bde5c1364fca33458.png" + top: -450 + left: -100 + right: -120 + bottom: -470 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "3V3:power" ] + - [ "PA12:gpio" ] + - [ "SWDIO:prog", "PA13:gpio" ] + - [ "SWCLK:prog", "PA14:gpio" ] + - [ "PA11:gpio" ] + - [ "PA15:gpio" ] + - [ "PB3:gpio" ] + - [ "PB4:gpio" ] + - [ "PB5:gpio"] + - [ "PB6:gpio"] + - [ "PB7:gpio"] + - [ "BOOT0:config", "PF4:gpio"] + - [ "PB8:gpio"] + - [ "PF3:gpio"] + - [ "RESET:button", "PF2:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "5V:power" ] + - [ "PA8:gpio" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "PA7:gpio" ] + - [ "KEY2:button", "PA6:gpio" ] + - [ "KEY1:button", "PA5:gpio"] + - [ "LED4:led", "PA4:gpio"] + - [ "LED3:led", "PA3:gpio"] + - [ "LED2:led", "PA2:gpio"] + - [ "PA1:gpio"] + - [ "PA0:gpio"] + - [ "GND:gnd"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' + config: + label: 'Config' + bgcolor: '#A060FF' diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json index b198c38c95..6450e4231c 100644 --- a/targets/embedfire-py32f030.json +++ b/targets/embedfire-py32f030.json @@ -1,86 +1,9 @@ { - "inherits": ["py32f030_64k_8k"], + "inherits": [ + "py32f030_64k_8k" + ], "flash-command": "pyocd load -t py32f003x8 {bin}", - "build-tags": ["embedfire_py32f030"] -} - -/* - -https://splitbrain.github.io/pinoutleaf - -title: "embedfire-py32f030" - -# dimensions counted in pins -width: 8 -height: 16 - -# images can be URLs, use adjustments to fit the pins -image: - front: - src: "https://img.sanishtech.com/u/d7efa5b8e309a987d89bf3f031a4b5e3.png" - top: -520 - left: -120 - right: -120 - bottom: -470 - back: - src: "https://img.sanishtech.com/u/cfc8cd0828646e3bde5c1364fca33458.png" - top: -450 - left: -100 - right: -120 - bottom: -470 - -# Define the pins (label:type), use empty entries when offsets are needed -pins: - left: - - [ "3V3:power" ] - - [ "PA12:gpio" ] - - [ "SWDIO:prog", "PA13:gpio" ] - - [ "SWCLK:prog", "PA14:gpio" ] - - [ "PA11:gpio" ] - - [ "PA15:gpio" ] - - [ "PB3:gpio" ] - - [ "PB4:gpio" ] - - [ "PB5:gpio"] - - [ "PB6:gpio"] - - [ "PB7:gpio"] - - [ "BOOT0:config", "PF4:gpio"] - - [ "PB8:gpio"] - - [ "PF3:gpio"] - - [ "RESET:button", "PF2:gpio"] - - [ "GND:gnd"] - right: - - [ "3V3:power" ] - - [ "5V:power" ] - - [ "PA8:gpio" ] - - [ "PB2:gpio" ] - - [ "PB1:gpio" ] - - [ "PB0:gpio" ] - - [ "PA7:gpio" ] - - [ "KEY2:button", "PA6:gpio" ] - - [ "KEY1:button", "PA5:gpio"] - - [ "LED4:led", "PA4:gpio"] - - [ "LED3:led", "PA3:gpio"] - - [ "LED2:led", "PA2:gpio"] - - [ "PA1:gpio"] - - [ "PA0:gpio"] - - [ "GND:gnd"] - - [ "GND:gnd"] - -types: - gpio: - label: 'GPIO' - bgcolor: '#00A060' - prog: - label: 'SWD' - bgcolor: '#FFCC00' - led: - label: 'LED' - bgcolor: '#0099FF' - button: - label: 'Button' - bgcolor: '#B0B0B0' - config: - label: 'Config' - bgcolor: '#A060FF' - -*/ \ No newline at end of file + "build-tags": [ + "embedfire_py32f030" + ] +} \ No newline at end of file diff --git a/targets/py32f002b.json b/targets/py32f002b.json index 2c0c82d8bc..33d29e5c16 100644 --- a/targets/py32f002b.json +++ b/targets/py32f002b.json @@ -3,7 +3,8 @@ "py32" ], "build-tags": [ - "py32f002bxx", "no_gpio_afrh" + "py32f002bxx", + "no_gpio_afrh" ], "linkerscript": "targets/py32f002b.ld", "extra-files": [ diff --git a/targets/py32f030.json b/targets/py32f030.json index e1bc19bed0..93f28e0277 100644 --- a/targets/py32f030.json +++ b/targets/py32f030.json @@ -3,7 +3,8 @@ "py32" ], "build-tags": [ - "py32f030", "py32f030xx" + "py32f030", + "py32f030xx" ], "extra-files": [ "src/device/py32/py32f030xx.s" From 452925cdb7dfe5e8663c0df9c4c7674c781ab715 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 16 Dec 2025 10:40:54 +0100 Subject: [PATCH 18/62] pinout yamls removed --- targets/embedfire-py32f002b-pinout.yaml | 63 -------------------- targets/embedfire-py32f030-pinout.yaml | 76 ------------------------- 2 files changed, 139 deletions(-) delete mode 100644 targets/embedfire-py32f002b-pinout.yaml delete mode 100644 targets/embedfire-py32f030-pinout.yaml diff --git a/targets/embedfire-py32f002b-pinout.yaml b/targets/embedfire-py32f002b-pinout.yaml deleted file mode 100644 index 44b1b634ab..0000000000 --- a/targets/embedfire-py32f002b-pinout.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# https://splitbrain.github.io/pinoutleaf - -title: "embedfire-py32f002b" - -# dimensions counted in pins -width: 8 -height: 11 - -# images can be URLs, use adjustments to fit the pins -image: - front: - src: "https://img.sanishtech.com/u/8f427259002707501b471ef06a77134c.png" - top: -450 - left: -90 - right: -90 - bottom: -450 - back: - src: "https://img.sanishtech.com/u/3650f247f0b77ef5efbcfca3d75f29aa.png" - top: -450 - left: -90 - right: -90 - bottom: -450 - -# Define the pins (label:type), use empty entries when offsets are needed -pins: - left: - - [ "5V:power" ] - - [ "PB2:gpio" ] - - [ "PB1:gpio" ] - - [ "PB0:gpio" ] - - [ "KEY2:button", "PA0:gpio" ] - - [ "LED2:led", "PA1:gpio" ] - - [ "SWCLK:prog", "PA2:gpio" ] - - [ "KEY1:button", "PA3:gpio" ] - - [ "LED4:led", "PA4:gpio"] - - [ "RESET:button", "PC0:gpio"] - - [ "GND:gnd"] - right: - - [ "3V3:power" ] - - [ "PB5:gpio" ] - - [ "PB4:gpio" ] - - [ "PB3:gpio" ] - - [ "SWDIO:prog", "PB6:gpio" ] - - [ "PB7:gpio" ] - - [ "PC1:gpio" ] - - [ "LED3:led", "PA5:gpio" ] - - [ "PA7:gpio"] - - [ "PA6:gpio"] - - [ "GND:gnd"] - -types: - gpio: - label: 'GPIO' - bgcolor: '#00A060' - prog: - label: 'SWD' - bgcolor: '#FFCC00' - led: - label: 'LED' - bgcolor: '#0099FF' - button: - label: 'Button' - bgcolor: '#B0B0B0' diff --git a/targets/embedfire-py32f030-pinout.yaml b/targets/embedfire-py32f030-pinout.yaml deleted file mode 100644 index d117235834..0000000000 --- a/targets/embedfire-py32f030-pinout.yaml +++ /dev/null @@ -1,76 +0,0 @@ -# https://splitbrain.github.io/pinoutleaf - -title: "embedfire-py32f030" - -# dimensions counted in pins -width: 8 -height: 16 - -# images can be URLs, use adjustments to fit the pins -image: - front: - src: "https://img.sanishtech.com/u/d7efa5b8e309a987d89bf3f031a4b5e3.png" - top: -520 - left: -120 - right: -120 - bottom: -470 - back: - src: "https://img.sanishtech.com/u/cfc8cd0828646e3bde5c1364fca33458.png" - top: -450 - left: -100 - right: -120 - bottom: -470 - -# Define the pins (label:type), use empty entries when offsets are needed -pins: - left: - - [ "3V3:power" ] - - [ "PA12:gpio" ] - - [ "SWDIO:prog", "PA13:gpio" ] - - [ "SWCLK:prog", "PA14:gpio" ] - - [ "PA11:gpio" ] - - [ "PA15:gpio" ] - - [ "PB3:gpio" ] - - [ "PB4:gpio" ] - - [ "PB5:gpio"] - - [ "PB6:gpio"] - - [ "PB7:gpio"] - - [ "BOOT0:config", "PF4:gpio"] - - [ "PB8:gpio"] - - [ "PF3:gpio"] - - [ "RESET:button", "PF2:gpio"] - - [ "GND:gnd"] - right: - - [ "3V3:power" ] - - [ "5V:power" ] - - [ "PA8:gpio" ] - - [ "PB2:gpio" ] - - [ "PB1:gpio" ] - - [ "PB0:gpio" ] - - [ "PA7:gpio" ] - - [ "KEY2:button", "PA6:gpio" ] - - [ "KEY1:button", "PA5:gpio"] - - [ "LED4:led", "PA4:gpio"] - - [ "LED3:led", "PA3:gpio"] - - [ "LED2:led", "PA2:gpio"] - - [ "PA1:gpio"] - - [ "PA0:gpio"] - - [ "GND:gnd"] - - [ "GND:gnd"] - -types: - gpio: - label: 'GPIO' - bgcolor: '#00A060' - prog: - label: 'SWD' - bgcolor: '#FFCC00' - led: - label: 'LED' - bgcolor: '#0099FF' - button: - label: 'Button' - bgcolor: '#B0B0B0' - config: - label: 'Config' - bgcolor: '#A060FF' From f88db400342d1a09078d41c502d2609e010c361b Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 6 Jan 2026 19:15:08 +0100 Subject: [PATCH 19/62] machine: implement default UART pin configuration for Embedfire boards --- src/machine/board_embedfire_py32f002b.go | 11 ++++------- src/machine/board_embedfire_py32f030.go | 11 ++++------- src/machine/machine_py32_uart.go | 12 +++--------- src/machine/machine_py32_uart_no_default_pins.go | 8 ++++++++ targets/embedfire-py32f002b.json | 3 ++- targets/embedfire-py32f030.json | 3 ++- 6 files changed, 23 insertions(+), 25 deletions(-) create mode 100644 src/machine/machine_py32_uart_no_default_pins.go diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index ab5ef80a6f..3a16d7db71 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -18,10 +18,7 @@ const ( KEY2 = PA0 ) -// UART -const ( - DEFAULT_UART_TX_PIN = PA6 - DEFAULT_UART_RX_PIN = PA7 - DEFAULT_UART_TX_PIN_AF = 1 - DEFAULT_UART_RX_PIN_AF = 3 -) +func configureDefaultUARTPins() { + ConfigureUARTPin(PA6, 1) // TX + ConfigureUARTPin(PA7, 3) // RX +} diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go index 7d32dab314..6f6324cea9 100644 --- a/src/machine/board_embedfire_py32f030.go +++ b/src/machine/board_embedfire_py32f030.go @@ -18,10 +18,7 @@ const ( KEY2 = PA6 ) -// UART -const ( - DEFAULT_UART_TX_PIN = PA7 - DEFAULT_UART_RX_PIN = PA8 - DEFAULT_UART_TX_PIN_AF = 8 - DEFAULT_UART_RX_PIN_AF = 8 -) +func configureDefaultUARTPins() { + ConfigureUARTPin(PA7, 8) // TX + ConfigureUARTPin(PA8, 8) // RX +} diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index 8cbe6fc27c..f605b0a884 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -23,19 +23,11 @@ var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer()} // ConfigureWithClock initializes the UART using the provided peripheral clock // frequency (in Hz). This avoids assuming a fixed MCU clock. func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { + if config.BaudRate == 0 { config.BaudRate = 115200 } - // Configure default pins if they weren't provided. - if config.TX == 0 { - ConfigureUARTPin(DEFAULT_UART_TX_PIN, DEFAULT_UART_TX_PIN_AF) - } - - if config.RX == 0 { - ConfigureUARTPin(DEFAULT_UART_RX_PIN, DEFAULT_UART_RX_PIN_AF) - } - // Enable peripheral clock. py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) @@ -56,6 +48,8 @@ func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { uart.irq.SetPriority(0xc0) uart.irq.Enable() + configureDefaultUARTPins() + return nil } diff --git a/src/machine/machine_py32_uart_no_default_pins.go b/src/machine/machine_py32_uart_no_default_pins.go new file mode 100644 index 0000000000..70259c145a --- /dev/null +++ b/src/machine/machine_py32_uart_no_default_pins.go @@ -0,0 +1,8 @@ +//go:build py32 && !default_uart_pins + +package machine + +func configureDefaultUARTPins() { + // There are no default UART pins for this board. Configure them in + // application main() using ConfigureUARTPin(). +} diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index b39aa5dc76..5183ac4225 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -4,6 +4,7 @@ ], "flash-command": "pyocd load -t py32f002bx5 {bin}", "build-tags": [ - "embedfire_py32f002b" + "embedfire_py32f002b", + "default_uart_pins" ] } \ No newline at end of file diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json index 6450e4231c..df4d999700 100644 --- a/targets/embedfire-py32f030.json +++ b/targets/embedfire-py32f030.json @@ -4,6 +4,7 @@ ], "flash-command": "pyocd load -t py32f003x8 {bin}", "build-tags": [ - "embedfire_py32f030" + "embedfire_py32f030", + "default_uart_pins" ] } \ No newline at end of file From 996f747bfa126fa063a287568daa2563872cbbee Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 27 Jan 2026 14:23:04 +0100 Subject: [PATCH 20/62] flash command moved to chip level so VS Code plugin can select bare chip --- targets/embedfire-py32f002b.json | 1 - targets/embedfire-py32f030.json | 1 - targets/py32f002b.json | 3 ++- targets/py32f030_64k_8k.json | 3 ++- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index 5183ac4225..cc9c8bcbdf 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -2,7 +2,6 @@ "inherits": [ "py32f002b" ], - "flash-command": "pyocd load -t py32f002bx5 {bin}", "build-tags": [ "embedfire_py32f002b", "default_uart_pins" diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json index df4d999700..3670d146aa 100644 --- a/targets/embedfire-py32f030.json +++ b/targets/embedfire-py32f030.json @@ -2,7 +2,6 @@ "inherits": [ "py32f030_64k_8k" ], - "flash-command": "pyocd load -t py32f003x8 {bin}", "build-tags": [ "embedfire_py32f030", "default_uart_pins" diff --git a/targets/py32f002b.json b/targets/py32f002b.json index 33d29e5c16..a4a87d7093 100644 --- a/targets/py32f002b.json +++ b/targets/py32f002b.json @@ -9,5 +9,6 @@ "linkerscript": "targets/py32f002b.ld", "extra-files": [ "src/device/py32/py32f002axx.s" - ] + ], + "flash-command": "pyocd load -t py32f002bx5 {bin}" } \ No newline at end of file diff --git a/targets/py32f030_64k_8k.json b/targets/py32f030_64k_8k.json index 6a248733d8..93a51e3675 100644 --- a/targets/py32f030_64k_8k.json +++ b/targets/py32f030_64k_8k.json @@ -5,5 +5,6 @@ "build-tags": [ "py32f030_64k_8k" ], - "linkerscript": "targets/py32f030_64k_8k.ld" + "linkerscript": "targets/py32f030_64k_8k.ld", + "flash-command": "pyocd load -t py32f003x8 {bin}" } \ No newline at end of file From 18afd7d37c737e94b75d4ba50026207f1ac2b10d Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 27 Jan 2026 16:14:01 +0100 Subject: [PATCH 21/62] machine: add support for alternate pin mode configuration --- src/machine/machine_py32_pin.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index d244439408..39c7ef56d8 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -141,14 +141,16 @@ const ( PinInputPulldown PinInputPullup PinInputAnalog + PinAlternate ) const PinInput PinMode = PinInputFloating const ( - gpioModeInput = 0 - gpioModeOutput = 1 - gpioModeAnalog = 3 - gpioModeMask = 0x3 + gpioModeInput = 0 + gpioModeOutput = 1 + gpioModeAlternate = 2 + gpioModeAnalog = 3 + gpioModeMask = 0x3 gpioPullFloating = 0 gpioPullUp = 1 @@ -211,6 +213,9 @@ func (p Pin) Configure(config PinConfig) { case PinInputAnalog: port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + case PinAlternate: + port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) + port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) } } From 61f12c5858f52703a0f878b329d4bcd42f238aac Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 27 Jan 2026 20:54:41 +0100 Subject: [PATCH 22/62] WIP --- src/machine/machine_py32_pin.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 39c7ef56d8..453ed42a6a 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -163,7 +163,6 @@ const ( func (p Pin) getPortNumber() uint8 { return uint8(p) >> 4 - } func (p Pin) getPinNumber() uint8 { From f57ef0deb3d6f9189dd08f4e799f8fe1ac5b7ac1 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 13 Feb 2026 15:23:10 +0100 Subject: [PATCH 23/62] WIP --- lib/bdwgc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bdwgc b/lib/bdwgc index 1166f11f7d..7577ca7c2d 160000 --- a/lib/bdwgc +++ b/lib/bdwgc @@ -1 +1 @@ -Subproject commit 1166f11f7dee08d7ad369296b24cf8c9582f8789 +Subproject commit 7577ca7c2dc7364bb6733dab23be34231279db6b From 65b696a47b75fec0275335533ca031e43e05c493 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 13 Feb 2026 19:09:53 +0100 Subject: [PATCH 24/62] WIP --- src/runtime/runtime_py32.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 4088d49b62..b552999f57 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -27,7 +27,7 @@ func main() { } // Configure SysTick to fire every 1ms on given system frequency. -// This should be called after any changes to the system clock frequency. +// This should be called after any change to the system clock frequency. func ConfigureSystemTimer(systemFrequencyHz uint32) { arm.SetupSystemTimer(systemFrequencyHz / 1000) } From d23c1bece407c58efb007ef8fb604e9154c77ae5 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 21 Feb 2026 00:16:09 +0100 Subject: [PATCH 25/62] add build targets for embedfire on py32 --- make/smoketest.mk | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/make/smoketest.mk b/make/smoketest.mk index fb97e595c7..4c2b63d660 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -19,6 +19,7 @@ SMOKETEST_SUBTARGETS = \ smoketest-rp2xxx \ smoketest-pwm-usb \ smoketest-stm32 \ + smoketest-py32 \ smoketest-avr \ smoketest-esp \ smoketest-riscv \ @@ -403,6 +404,17 @@ ifneq ($(STM32), 0) @$(MD5SUM) $(SMOKE_OUT).hex endif +smoketest-py32: SMOKE_OUT = build/smoke/py32 +smoketest-py32: | build/smoke + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f030 examples/blinky1 + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f030 examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f002b examples/blinky1 + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f002b examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex + smoketest-avr: SMOKE_OUT = build/smoke/avr smoketest-avr: | build/smoke $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=atmega328pb examples/blinkm From 8cabb444768f824d1b5ded2ae9d6d524833337bd Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 21 Feb 2026 00:49:52 +0100 Subject: [PATCH 26/62] add support for embedfire target in GNUmakefile for py32 --- make/smoketest.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/smoketest.mk b/make/smoketest.mk index 4c2b63d660..d313908d74 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -406,6 +406,7 @@ endif smoketest-py32: SMOKE_OUT = build/smoke/py32 smoketest-py32: | build/smoke +ifneq ($(PY32), 0) $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f030 examples/blinky1 @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f030 examples/echo @@ -414,6 +415,7 @@ smoketest-py32: | build/smoke @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f002b examples/echo @$(MD5SUM) $(SMOKE_OUT).hex +endif smoketest-avr: SMOKE_OUT = build/smoke/avr smoketest-avr: | build/smoke From bc6203eb5ae7b7adf0e4aecf0a57fdddd1b7e073 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 21 Feb 2026 19:22:19 +0100 Subject: [PATCH 27/62] lib/py32-svd: remove duplicate DBGMCU.IDCODE CODE field Update submodule to fix duplicate SetIDCODE/GetIDCODE method declarations in the generated py32f002bxx.go device file. Co-Authored-By: Claude Sonnet 4.6 --- lib/py32-svd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/py32-svd b/lib/py32-svd index d98c758f53..31fc271d43 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit d98c758f530cfa61e607334b50e19f6c113f8d1d +Subproject commit 31fc271d431c1abd67990bed8db34ab31149ff57 From 590794c5cdcef57217303b3ba61fedee8fce81dd Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 21 Feb 2026 19:51:28 +0100 Subject: [PATCH 28/62] update subproject commit reference in py32-svd --- lib/py32-svd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/py32-svd b/lib/py32-svd index 31fc271d43..cf204623eb 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit 31fc271d431c1abd67990bed8db34ab31149ff57 +Subproject commit cf204623eb20469914688563f748dc8b4a63cf65 From 4e4fa597a71c1dc693429525705fb06ab3ba0b95 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 4 Mar 2026 00:26:05 +0100 Subject: [PATCH 29/62] PR fixes --- src/machine/machine_py32_clock.go | 18 +++++++++++++++++ src/machine/machine_py32_pin.go | 29 +++++++++++++++------------- src/machine/machine_py32_uart.go | 32 ++++--------------------------- src/runtime/runtime_py32.go | 7 ++++--- targets/embedfire-py32f002b.json | 2 +- 5 files changed, 43 insertions(+), 45 deletions(-) create mode 100644 src/machine/machine_py32_clock.go diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go new file mode 100644 index 0000000000..a14ce4e81f --- /dev/null +++ b/src/machine/machine_py32_clock.go @@ -0,0 +1,18 @@ +//go:build py32 + +package machine + +var CPUFrequencyHz uint32 + +func CPUFrequency() uint32 { + return CPUFrequencyHz +} + +// SetCPUFrequency sets the CPU frequency in hertz. +// Called by runtime.main() with the default frequency, and can be called by user code to change the frequency at runtime. +// Note that peripherals may need re-initialization after a frequency change: +// - runtime.ConfigureSystemTimer() for the system timer +// - machine.DefaultUART.Configure() if UART is in use +func SetCPUFrequency(frequency uint32) { + CPUFrequencyHz = frequency +} diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 453ed42a6a..0409411e52 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -146,19 +146,22 @@ const ( const PinInput PinMode = PinInputFloating const ( - gpioModeInput = 0 - gpioModeOutput = 1 - gpioModeAlternate = 2 - gpioModeAnalog = 3 - gpioModeMask = 0x3 - - gpioPullFloating = 0 - gpioPullUp = 1 - gpioPullDown = 2 - gpioPullMask = 0x3 - - gpioOutputSpeedHigh = 2 - gpioOutputSpeedMask = 0x3 + gpioModeInput = py32.GPIO_MODER_MODE0_Input + gpioModeOutput = py32.GPIO_MODER_MODE0_Output + gpioModeAlternate = py32.GPIO_MODER_MODE0_Alternate + gpioModeAnalog = py32.GPIO_MODER_MODE0_Analog + gpioModeMask = py32.GPIO_MODER_MODE0_Msk + + gpioPullFloating = py32.GPIO_PUPDR_PUPD0_Floating + gpioPullUp = py32.GPIO_PUPDR_PUPD0_PullUp + gpioPullDown = py32.GPIO_PUPDR_PUPD0_PullDown + gpioPullMask = py32.GPIO_PUPDR_PUPD0_Msk + + gpioOutputSpeedLow = py32.GPIO_OSPEEDR_OSPEED0_LowSpeed + gpioOutputSpeedMedium = py32.GPIO_OSPEEDR_OSPEED0_MediumSpeed + gpioOutputSpeedHigh = py32.GPIO_OSPEEDR_OSPEED0_HighSpeed + gpioOutputSpeedVeryHigh = py32.GPIO_OSPEEDR_OSPEED0_VeryHighSpeed + gpioOutputSpeedMask = py32.GPIO_OSPEEDR_OSPEED0_Msk ) func (p Pin) getPortNumber() uint8 { diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index f605b0a884..471895a5de 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -7,10 +7,6 @@ import ( "runtime/interrupt" ) -// Remember the clock used for baud rate calculations so Configure() can be -// called without explicitly passing the clock. -var py32UARTClockHz uint32 = 24_000_000 - // UART implements a minimal USART1 driver for PY32 parts. type UART struct { Bus *py32.USART_Type @@ -20,9 +16,7 @@ type UART struct { var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer()} -// ConfigureWithClock initializes the UART using the provided peripheral clock -// frequency (in Hz). This avoids assuming a fixed MCU clock. -func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { +func (uart *UART) Configure(config UARTConfig) error { if config.BaudRate == 0 { config.BaudRate = 115200 @@ -36,6 +30,8 @@ func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { uart.Bus.CR2.Set(0) uart.Bus.CR3.Set(0) + clockHz := CPUFrequency() + // Oversampling by 16: BRR expects fck/baud. divider := (clockHz + (config.BaudRate / 2)) / config.BaudRate uart.Bus.BRR.Set(divider) @@ -53,29 +49,9 @@ func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { return nil } -// Configure uses the last stored clock (defaulting to 24 MHz). Call -// ConfigureWithClock for explicit control. -func (uart *UART) Configure(config UARTConfig) error { - return uart.ConfigureWithClock(config, py32UARTClockHz) -} - -// InitSerialWithClock configures the default Serial using the supplied -// peripheral clock frequency. -func InitSerialWithClock(clockHz uint32) { - py32UARTClockHz = clockHz - //Serial.ConfigureWithClock(UARTConfig{}, clockHz) -} - // Configure pin for use by UART func ConfigureUARTPin(pin Pin, af uint8) { - pin.enableClock() - port, n := pin.getPort() - pos := (n % 16) * 2 - - // Alternate function mode is encoded as 0b10. - port.MODER.ReplaceBits(2, gpioModeMask, pos) - port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) - port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + pin.Configure(PinConfig{Mode: PinAlternate}) pin.SetAltFunc(af) } diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index b552999f57..61e776b117 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -19,7 +19,8 @@ func main() { py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) - ConfigureSystemTimer(24_000_000) + machine.SetCPUFrequency(24_000_000) + ConfigureSystemTimer() machine.InitSerial() run() @@ -28,8 +29,8 @@ func main() { // Configure SysTick to fire every 1ms on given system frequency. // This should be called after any change to the system clock frequency. -func ConfigureSystemTimer(systemFrequencyHz uint32) { - arm.SetupSystemTimer(systemFrequencyHz / 1000) +func ConfigureSystemTimer() { + arm.SetupSystemTimer(machine.CPUFrequency() / 1000) } func ticksToNanoseconds(ticks timeUnit) int64 { diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index cc9c8bcbdf..33eaaa51d7 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -4,6 +4,6 @@ ], "build-tags": [ "embedfire_py32f002b", - "default_uart_pins" + "default_uart_pins" ] } \ No newline at end of file From 0932f828c22a24e857cb4195a1bd6962a9fb02a3 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 4 Mar 2026 09:45:04 +0100 Subject: [PATCH 30/62] refactor: update CPU frequency handling in machine and runtime packages --- src/machine/machine_py32_clock.go | 15 +++++---------- src/runtime/runtime_py32.go | 1 - 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index a14ce4e81f..0414a55df3 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,17 +2,12 @@ package machine -var CPUFrequencyHz uint32 +// This variable must be updated after any change to the system clock from user code. +// Don't forget to re-initialize peripherals that depend on the system clock, such as: +// - runtime.ConfigureSystemTimer() for the system timer +// - machine.DefaultUART.Configure() if UART is in use +var CPUFrequencyHz uint32 = 24_000_000 func CPUFrequency() uint32 { return CPUFrequencyHz } - -// SetCPUFrequency sets the CPU frequency in hertz. -// Called by runtime.main() with the default frequency, and can be called by user code to change the frequency at runtime. -// Note that peripherals may need re-initialization after a frequency change: -// - runtime.ConfigureSystemTimer() for the system timer -// - machine.DefaultUART.Configure() if UART is in use -func SetCPUFrequency(frequency uint32) { - CPUFrequencyHz = frequency -} diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 61e776b117..b29c5fe91d 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -19,7 +19,6 @@ func main() { py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) - machine.SetCPUFrequency(24_000_000) ConfigureSystemTimer() machine.InitSerial() From e807081c88b214f075c054e9e972b86c3f8052e0 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 3 May 2026 16:44:14 +0200 Subject: [PATCH 31/62] refactor: replace ConfigureUARTPin function with direct pin configuration in UART setup --- src/machine/board_embedfire_py32f002b.go | 6 ++++-- src/machine/board_embedfire_py32f030.go | 6 ++++-- src/machine/machine_py32_uart.go | 6 ------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index 3a16d7db71..ce6b7886a9 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -19,6 +19,8 @@ const ( ) func configureDefaultUARTPins() { - ConfigureUARTPin(PA6, 1) // TX - ConfigureUARTPin(PA7, 3) // RX + PA6.Configure(PinConfig{Mode: PinAlternate}) + PA6.SetAltFunc(1) + PA7.Configure(PinConfig{Mode: PinAlternate}) + PA7.SetAltFunc(3) } diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go index 6f6324cea9..f6d5bbe434 100644 --- a/src/machine/board_embedfire_py32f030.go +++ b/src/machine/board_embedfire_py32f030.go @@ -19,6 +19,8 @@ const ( ) func configureDefaultUARTPins() { - ConfigureUARTPin(PA7, 8) // TX - ConfigureUARTPin(PA8, 8) // RX + PA7.Configure(PinConfig{Mode: PinAlternate}) + PA7.SetAltFunc(8) + PA8.Configure(PinConfig{Mode: PinAlternate}) + PA8.SetAltFunc(8) } diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index 471895a5de..b3db66bf0e 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -49,12 +49,6 @@ func (uart *UART) Configure(config UARTConfig) error { return nil } -// Configure pin for use by UART -func ConfigureUARTPin(pin Pin, af uint8) { - pin.Configure(PinConfig{Mode: PinAlternate}) - pin.SetAltFunc(af) -} - func handleUartInterrupt(interrupt.Interrupt) { uart := DefaultUART data := uint8(uart.Bus.DR.Get()) From 8f7d05014dca34d215e97fea58983e1929c81cba Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 3 May 2026 18:27:07 +0200 Subject: [PATCH 32/62] SetAltFunc documentation for GPIO pin alternate functions --- src/machine/machine_py32_pin_afrh.go | 12 ++++++++++++ src/machine/machine_py32_pin_no_afrh.go | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 7077bd4de8..02ec04cda3 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -2,6 +2,18 @@ package machine +// SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. +// +// Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a +// 4-bit field in the GPIO alternate-function registers. The register is split +// in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for +// pins 8–15, with each selector at bit offset (pin%8)*4 within its register. +// +// AF0 is the system function (typically GPIO / SWDIO / SWCLK on JTAG pins). +// AF1–AF7 map peripherals such as USART, SPI, I2C, TIM, and MCO depending on +// the specific pin and PY32F variant; consult the alternate-function table in +// the device datasheet. The pin must also be configured as PinAlternate via +// Pin.Configure before the alternate function takes effect. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() if pin >= 8 { diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index fb674db8f4..32c471de16 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -2,6 +2,18 @@ package machine +// SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. +// +// Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a +// 4-bit field in the GPIO alternate-function registers. The register is split +// in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for +// pins 8–15, with each selector at bit offset (pin%8)*4 within its register. +// +// AF0 is the system function (typically GPIO / SWDIO / SWCLK on JTAG pins). +// AF1–AF7 map peripherals such as USART, SPI, I2C, TIM, and MCO depending on +// the specific pin and PY32F variant; consult the alternate-function table in +// the device datasheet. The pin must also be configured as PinAlternate via +// Pin.Configure before the alternate function takes effect. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) From f1df998cdd5cc7615d61764dca9220955c90b742 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sun, 3 May 2026 18:39:20 +0200 Subject: [PATCH 33/62] refactor: improve UART write and flush error handling with timeout --- src/machine/machine_py32_uart.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index b3db66bf0e..1efa9f14a2 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -7,6 +7,21 @@ import ( "runtime/interrupt" ) +// errUARTWriteTimeout is returned by writeByte when the TX register does not +// become empty within the retry budget. +type uartError string + +func (e uartError) Error() string { return string(e) } + +const errUARTWriteTimeout uartError = "UART: write timeout" + +// uartTXRetries is the upper bound on the SR polling loop in writeByte and +// flush. At the PY32F maximum CPU frequency of 48 MHz, an APB peripheral read +// plus loop overhead costs roughly 5 cycles (~104 ns). One byte at 9600 baud +// takes ~1.04 ms, which at that rate corresponds to ~10 000 iterations — the +// worst case for any standard baud rate at the highest supported clock. +const uartTXRetries = 10000 + // UART implements a minimal USART1 driver for PY32 parts. type UART struct { Bus *py32.USART_Type @@ -56,13 +71,20 @@ func handleUartInterrupt(interrupt.Interrupt) { } func (uart *UART) writeByte(c byte) error { - for uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { + retries := uartTXRetries + for retries > 0 && uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { + retries-- + } + if retries <= 0 { + return errUARTWriteTimeout } uart.Bus.DR.Set(uint32(c)) return nil } func (uart *UART) flush() { - for uart.Bus.SR.Get()&py32.USART_SR_TC == 0 { + retries := uartTXRetries + for retries > 0 && uart.Bus.SR.Get()&py32.USART_SR_TC == 0 { + retries-- } } From 7ba07678fbae44a6a714cee8fb7cc420bf9daa70 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 14 Jul 2026 17:33:49 +0200 Subject: [PATCH 34/62] machine/py32: generalize UART driver to any USART Add a per-instance setup func to the UART type so the driver is no longer hardwired to USART1. DefaultUART stays USART1; add UART2 (USART2) in a separately build-tagged file since py32f002x parts lack USART2. RX IRQ handlers reference runtime-assigned vars to break the init cycle, and setup is assigned in the var initializer so it runs before InitSerial. Add the py32f003_32k_4k target (32K flash / 4K RAM). --- src/machine/machine_py32_uart.go | 41 +++++++++++++++++++++---------- src/machine/machine_py32_uart2.go | 30 ++++++++++++++++++++++ targets/py32f003_32k_4k.json | 13 ++++++++++ targets/py32f003_32k_4k.ld | 10 ++++++++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 src/machine/machine_py32_uart2.go create mode 100644 targets/py32f003_32k_4k.json create mode 100644 targets/py32f003_32k_4k.ld diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index 1efa9f14a2..ea97f1c15a 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -22,14 +22,19 @@ const errUARTWriteTimeout uartError = "UART: write timeout" // worst case for any standard baud rate at the highest supported clock. const uartTXRetries = 10000 -// UART implements a minimal USART1 driver for PY32 parts. +// UART implements a minimal USART driver for PY32 parts. It works with any of +// the on-chip USART peripherals: the peripheral-specific wiring (clock gate and +// RX interrupt) is provided by the setup function stored on the instance, which +// is set when the instance is created (see setupUSART1 / setupUSART2). type UART struct { Bus *py32.USART_Type Buffer *RingBuffer irq interrupt.Interrupt + setup func(*UART) } -var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer()} +// DefaultUART is the first USART (USART1) and backs machine.Serial. +var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer(), setup: setupUSART1} func (uart *UART) Configure(config UARTConfig) error { @@ -37,8 +42,8 @@ func (uart *UART) Configure(config UARTConfig) error { config.BaudRate = 115200 } - // Enable peripheral clock. - py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) + // Enable the peripheral clock and hook its RX interrupt. + uart.setup(uart) // Reset control registers to a known state. uart.Bus.CR1.Set(0) @@ -54,22 +59,32 @@ func (uart *UART) Configure(config UARTConfig) error { // Enable transmitter, receiver, RX interrupt, and the peripheral. uart.Bus.CR1.Set(py32.USART_CR1_TE | py32.USART_CR1_RE | py32.USART_CR1_RXNEIE | py32.USART_CR1_UE) - // Hook interrupt. - uart.irq = interrupt.New(py32.IRQ_USART1, handleUartInterrupt) - uart.irq.SetPriority(0xc0) - uart.irq.Enable() - configureDefaultUARTPins() return nil } -func handleUartInterrupt(interrupt.Interrupt) { - uart := DefaultUART - data := uint8(uart.Bus.DR.Get()) - uart.Receive(data) +// setupUSART1 enables the USART1 peripheral clock and installs its RX interrupt +// handler. It records the instance in usart1RX so the handler can reach it +// without the var initializer forming an initialization cycle. +func setupUSART1(uart *UART) { + usart1RX = uart + py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) + uart.irq = interrupt.New(py32.IRQ_USART1, handleUSART1Interrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() +} + +func handleUSART1Interrupt(interrupt.Interrupt) { + usart1RX.Receive(uint8(usart1RX.Bus.DR.Get())) } +// usart1RX is the UART whose RX interrupt is serviced by handleUSART1Interrupt. +// It is set by setupUSART1 at Configure time; keeping it as a plain package var +// (rather than referencing DefaultUART from the handler) avoids an +// initialization cycle so DefaultUART.setup can be set in its var initializer. +var usart1RX *UART + func (uart *UART) writeByte(c byte) error { retries := uartTXRetries for retries > 0 && uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { diff --git a/src/machine/machine_py32_uart2.go b/src/machine/machine_py32_uart2.go new file mode 100644 index 0000000000..12db23a464 --- /dev/null +++ b/src/machine/machine_py32_uart2.go @@ -0,0 +1,30 @@ +//go:build py32f003xx || py32f030xx || py32f040xx + +package machine + +import ( + "device/py32" + "runtime/interrupt" +) + +// UART2 is the second USART (USART2), available on PY32 parts that provide it. +// It shares the generic UART driver; its clock gate and interrupt are wired up +// by setupUSART2. +var UART2 = &UART{Bus: py32.USART2, Buffer: NewRingBuffer(), setup: setupUSART2} + +// setupUSART2 enables the USART2 peripheral clock and installs its RX interrupt +// handler. +func setupUSART2(uart *UART) { + usart2RX = uart + py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_USART2EN) + uart.irq = interrupt.New(py32.IRQ_USART2, handleUSART2Interrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() +} + +func handleUSART2Interrupt(interrupt.Interrupt) { + usart2RX.Receive(uint8(usart2RX.Bus.DR.Get())) +} + +// usart2RX is the UART serviced by handleUSART2Interrupt, set by setupUSART2. +var usart2RX *UART diff --git a/targets/py32f003_32k_4k.json b/targets/py32f003_32k_4k.json new file mode 100644 index 0000000000..f83fd7eb84 --- /dev/null +++ b/targets/py32f003_32k_4k.json @@ -0,0 +1,13 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f003xx" + ], + "linkerscript": "targets/py32f003_32k_4k.ld", + "extra-files": [ + "src/device/py32/py32f003xx.s" + ], + "flash-command": "pyocd load -t py32f003 {bin}" +} \ No newline at end of file diff --git a/targets/py32f003_32k_4k.ld b/targets/py32f003_32k_4k.ld new file mode 100644 index 0000000000..3778f78680 --- /dev/null +++ b/targets/py32f003_32k_4k.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" \ No newline at end of file From 666c5662412a80ad8217cc9d4f431c95a53a7331 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Tue, 4 Aug 2026 22:40:22 +0200 Subject: [PATCH 35/62] Add canonical PY32F002, F003, and F030 density targets Use CMSIS/pyocd device names for target files and build tags. Add all F003 and F030 densities plus F002A/B, correct F002B to 24K flash and its own startup file, fix the F030x8 pyocd target, and update Embedfire inheritance. --- targets/embedfire-py32f002b.json | 2 +- targets/embedfire-py32f030.json | 2 +- targets/py32f002ax5.json | 14 ++++++++++++++ targets/{py32f002b.ld => py32f002ax5.ld} | 2 +- targets/{py32f002b.json => py32f002bx5.json} | 6 +++--- targets/py32f002bx5.ld | 10 ++++++++++ targets/{py32f003_32k_4k.json => py32f003.json} | 6 ++---- targets/py32f003x4.json | 10 ++++++++++ targets/py32f003x4.ld | 10 ++++++++++ targets/py32f003x6.json | 10 ++++++++++ targets/{py32f003_32k_4k.ld => py32f003x6.ld} | 2 +- targets/py32f003x7.json | 10 ++++++++++ targets/py32f003x7.ld | 10 ++++++++++ targets/py32f003x8.json | 10 ++++++++++ targets/py32f003x8.ld | 10 ++++++++++ targets/py32f030_64k_8k.json | 10 ---------- targets/py32f030x4.json | 10 ++++++++++ targets/py32f030x4.ld | 10 ++++++++++ targets/py32f030x6.json | 10 ++++++++++ targets/py32f030x6.ld | 10 ++++++++++ targets/py32f030x7.json | 10 ++++++++++ targets/py32f030x7.ld | 10 ++++++++++ targets/py32f030x8.json | 10 ++++++++++ targets/{py32f030_64k_8k.ld => py32f030x8.ld} | 0 24 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 targets/py32f002ax5.json rename targets/{py32f002b.ld => py32f002ax5.ld} (84%) rename targets/{py32f002b.json => py32f002bx5.json} (69%) create mode 100644 targets/py32f002bx5.ld rename targets/{py32f003_32k_4k.json => py32f003.json} (57%) create mode 100644 targets/py32f003x4.json create mode 100644 targets/py32f003x4.ld create mode 100644 targets/py32f003x6.json rename targets/{py32f003_32k_4k.ld => py32f003x6.ld} (84%) create mode 100644 targets/py32f003x7.json create mode 100644 targets/py32f003x7.ld create mode 100644 targets/py32f003x8.json create mode 100644 targets/py32f003x8.ld delete mode 100644 targets/py32f030_64k_8k.json create mode 100644 targets/py32f030x4.json create mode 100644 targets/py32f030x4.ld create mode 100644 targets/py32f030x6.json create mode 100644 targets/py32f030x6.ld create mode 100644 targets/py32f030x7.json create mode 100644 targets/py32f030x7.ld create mode 100644 targets/py32f030x8.json rename targets/{py32f030_64k_8k.ld => py32f030x8.ld} (100%) diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index 33eaaa51d7..a58884aabe 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f002b" + "py32f002bx5" ], "build-tags": [ "embedfire_py32f002b", diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json index 3670d146aa..1a636819cb 100644 --- a/targets/embedfire-py32f030.json +++ b/targets/embedfire-py32f030.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f030_64k_8k" + "py32f030x8" ], "build-tags": [ "embedfire_py32f030", diff --git a/targets/py32f002ax5.json b/targets/py32f002ax5.json new file mode 100644 index 0000000000..b385ac3428 --- /dev/null +++ b/targets/py32f002ax5.json @@ -0,0 +1,14 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002axx", + "no_gpio_afrh" + ], + "linkerscript": "targets/py32f002ax5.ld", + "extra-files": [ + "src/device/py32/py32f002axx.s" + ], + "flash-command": "pyocd load -t py32f002ax5 {bin}" +} diff --git a/targets/py32f002b.ld b/targets/py32f002ax5.ld similarity index 84% rename from targets/py32f002b.ld rename to targets/py32f002ax5.ld index 3ed1dc12d0..766850cc45 100644 --- a/targets/py32f002b.ld +++ b/targets/py32f002ax5.ld @@ -7,4 +7,4 @@ MEMORY _stack_size = 512; -INCLUDE "targets/arm.ld" \ No newline at end of file +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002b.json b/targets/py32f002bx5.json similarity index 69% rename from targets/py32f002b.json rename to targets/py32f002bx5.json index a4a87d7093..9f5355754d 100644 --- a/targets/py32f002b.json +++ b/targets/py32f002bx5.json @@ -6,9 +6,9 @@ "py32f002bxx", "no_gpio_afrh" ], - "linkerscript": "targets/py32f002b.ld", + "linkerscript": "targets/py32f002bx5.ld", "extra-files": [ - "src/device/py32/py32f002axx.s" + "src/device/py32/py32f002bxx.s" ], "flash-command": "pyocd load -t py32f002bx5 {bin}" -} \ No newline at end of file +} diff --git a/targets/py32f002bx5.ld b/targets/py32f002bx5.ld new file mode 100644 index 0000000000..dde2f066e9 --- /dev/null +++ b/targets/py32f002bx5.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 24K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 3K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f003_32k_4k.json b/targets/py32f003.json similarity index 57% rename from targets/py32f003_32k_4k.json rename to targets/py32f003.json index f83fd7eb84..1e8aaca9d2 100644 --- a/targets/py32f003_32k_4k.json +++ b/targets/py32f003.json @@ -5,9 +5,7 @@ "build-tags": [ "py32f003xx" ], - "linkerscript": "targets/py32f003_32k_4k.ld", "extra-files": [ "src/device/py32/py32f003xx.s" - ], - "flash-command": "pyocd load -t py32f003 {bin}" -} \ No newline at end of file + ] +} diff --git a/targets/py32f003x4.json b/targets/py32f003x4.json new file mode 100644 index 0000000000..0a6a7ca207 --- /dev/null +++ b/targets/py32f003x4.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f003" + ], + "build-tags": [ + "py32f003x4" + ], + "linkerscript": "targets/py32f003x4.ld", + "flash-command": "pyocd load -t py32f003x4 {bin}" +} diff --git a/targets/py32f003x4.ld b/targets/py32f003x4.ld new file mode 100644 index 0000000000..71f4b877c4 --- /dev/null +++ b/targets/py32f003x4.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x6.json b/targets/py32f003x6.json new file mode 100644 index 0000000000..2081664535 --- /dev/null +++ b/targets/py32f003x6.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f003" + ], + "build-tags": [ + "py32f003x6" + ], + "linkerscript": "targets/py32f003x6.ld", + "flash-command": "pyocd load -t py32f003x6 {bin}" +} diff --git a/targets/py32f003_32k_4k.ld b/targets/py32f003x6.ld similarity index 84% rename from targets/py32f003_32k_4k.ld rename to targets/py32f003x6.ld index 3778f78680..56ef9222f5 100644 --- a/targets/py32f003_32k_4k.ld +++ b/targets/py32f003x6.ld @@ -7,4 +7,4 @@ MEMORY _stack_size = 512; -INCLUDE "targets/arm.ld" \ No newline at end of file +INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x7.json b/targets/py32f003x7.json new file mode 100644 index 0000000000..4184c47f65 --- /dev/null +++ b/targets/py32f003x7.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f003" + ], + "build-tags": [ + "py32f003x7" + ], + "linkerscript": "targets/py32f003x7.ld", + "flash-command": "pyocd load -t py32f003x7 {bin}" +} diff --git a/targets/py32f003x7.ld b/targets/py32f003x7.ld new file mode 100644 index 0000000000..9493be4cf1 --- /dev/null +++ b/targets/py32f003x7.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 48K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x8.json b/targets/py32f003x8.json new file mode 100644 index 0000000000..fbd21f80b6 --- /dev/null +++ b/targets/py32f003x8.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f003" + ], + "build-tags": [ + "py32f003x8" + ], + "linkerscript": "targets/py32f003x8.ld", + "flash-command": "pyocd load -t py32f003x8 {bin}" +} diff --git a/targets/py32f003x8.ld b/targets/py32f003x8.ld new file mode 100644 index 0000000000..c0b64037cf --- /dev/null +++ b/targets/py32f003x8.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f030_64k_8k.json b/targets/py32f030_64k_8k.json deleted file mode 100644 index 93a51e3675..0000000000 --- a/targets/py32f030_64k_8k.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "inherits": [ - "py32f030" - ], - "build-tags": [ - "py32f030_64k_8k" - ], - "linkerscript": "targets/py32f030_64k_8k.ld", - "flash-command": "pyocd load -t py32f003x8 {bin}" -} \ No newline at end of file diff --git a/targets/py32f030x4.json b/targets/py32f030x4.json new file mode 100644 index 0000000000..8da7c34b2c --- /dev/null +++ b/targets/py32f030x4.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030x4" + ], + "linkerscript": "targets/py32f030x4.ld", + "flash-command": "pyocd load -t py32f030x4 {bin}" +} diff --git a/targets/py32f030x4.ld b/targets/py32f030x4.ld new file mode 100644 index 0000000000..71f4b877c4 --- /dev/null +++ b/targets/py32f030x4.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x6.json b/targets/py32f030x6.json new file mode 100644 index 0000000000..27b3e0849c --- /dev/null +++ b/targets/py32f030x6.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030x6" + ], + "linkerscript": "targets/py32f030x6.ld", + "flash-command": "pyocd load -t py32f030x6 {bin}" +} diff --git a/targets/py32f030x6.ld b/targets/py32f030x6.ld new file mode 100644 index 0000000000..56ef9222f5 --- /dev/null +++ b/targets/py32f030x6.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x7.json b/targets/py32f030x7.json new file mode 100644 index 0000000000..7d611efbb4 --- /dev/null +++ b/targets/py32f030x7.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030x7" + ], + "linkerscript": "targets/py32f030x7.ld", + "flash-command": "pyocd load -t py32f030x7 {bin}" +} diff --git a/targets/py32f030x7.ld b/targets/py32f030x7.ld new file mode 100644 index 0000000000..9493be4cf1 --- /dev/null +++ b/targets/py32f030x7.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 48K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x8.json b/targets/py32f030x8.json new file mode 100644 index 0000000000..f4e992b73d --- /dev/null +++ b/targets/py32f030x8.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030x8" + ], + "linkerscript": "targets/py32f030x8.ld", + "flash-command": "pyocd load -t py32f030x8 {bin}" +} \ No newline at end of file diff --git a/targets/py32f030_64k_8k.ld b/targets/py32f030x8.ld similarity index 100% rename from targets/py32f030_64k_8k.ld rename to targets/py32f030x8.ld From 6e4d9414b0fd516ee4f72d3741736fbca2290ac3 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 5 Aug 2026 23:09:56 +0200 Subject: [PATCH 36/62] Add targets for all PY32 CMSIS devices --- compileopts/target_test.go | 34 +++++ lib/py32-svd | 2 +- make/gen-device.mk | 5 +- src/machine/machine_py32_pin.go | 28 ++-- src/runtime/runtime_py32.go | 5 +- targets/py32-m4.json | 10 ++ targets/py32e407xc.json | 9 ++ targets/py32e407xc.ld | 9 ++ targets/py32e407xd.json | 9 ++ targets/py32e407xd.ld | 9 ++ targets/py32e407xe.json | 9 ++ targets/py32e407xe.ld | 9 ++ targets/py32e407xx.json | 11 ++ targets/py32f001cx4.json | 9 ++ targets/py32f001cx4.ld | 9 ++ targets/py32f001cxx.json | 12 ++ targets/py32f001xx.json | 11 ++ targets/py32f002axx.json | 11 ++ targets/py32f002bxx.json | 12 ++ targets/py32f002cx5.json | 9 ++ targets/py32f002cx5.ld | 9 ++ targets/py32f002cxx.json | 12 ++ targets/py32f002xx2.json | 9 ++ targets/py32f002xx2.ld | 9 ++ targets/py32f002xx4.json | 9 ++ targets/py32f002xx4.ld | 9 ++ targets/py32f002xx5.json | 9 ++ targets/py32f002xx5.ld | 9 ++ targets/py32f002xxx.json | 12 ++ targets/py32f002zx4.json | 9 ++ targets/py32f002zx4.ld | 9 ++ targets/py32f002zxx.json | 12 ++ targets/py32f003xx.json | 11 ++ targets/py32f021x8.json | 9 ++ targets/py32f021x8.ld | 9 ++ targets/py32f021xx.json | 11 ++ targets/py32f030xx.json | 11 ++ targets/py32f031x4.json | 9 ++ targets/py32f031x4.ld | 9 ++ targets/py32f031x6.json | 9 ++ targets/py32f031x6.ld | 9 ++ targets/py32f031x7.json | 9 ++ targets/py32f031x7.ld | 9 ++ targets/py32f031x8.json | 9 ++ targets/py32f031x8.ld | 9 ++ targets/py32f031xx.json | 11 ++ targets/py32f032x8.json | 9 ++ targets/py32f032x8.ld | 9 ++ targets/py32f032xx.json | 11 ++ targets/py32f040cx6.json | 9 ++ targets/py32f040cx6.ld | 9 ++ targets/py32f040cx8.json | 9 ++ targets/py32f040cx8.ld | 9 ++ targets/py32f040cx9.json | 9 ++ targets/py32f040cx9.ld | 9 ++ targets/py32f040cxb.json | 9 ++ targets/py32f040cxb.ld | 9 ++ targets/py32f040cxx.json | 11 ++ targets/py32f040epxb.json | 9 ++ targets/py32f040epxb.ld | 9 ++ targets/py32f040epxx.json | 11 ++ targets/py32f040ex6.json | 9 ++ targets/py32f040ex6.ld | 9 ++ targets/py32f040ex8.json | 9 ++ targets/py32f040ex8.ld | 9 ++ targets/py32f040ex9.json | 9 ++ targets/py32f040ex9.ld | 9 ++ targets/py32f040exb.json | 9 ++ targets/py32f040exb.ld | 9 ++ targets/py32f040exx.json | 11 ++ targets/py32f040x6.json | 9 ++ targets/py32f040x6.ld | 9 ++ targets/py32f040x8.json | 9 ++ targets/py32f040x8.ld | 9 ++ targets/py32f040x9.json | 9 ++ targets/py32f040x9.ld | 9 ++ targets/py32f040xb.json | 9 ++ targets/py32f040xb.ld | 9 ++ targets/py32f040xx.json | 11 ++ targets/py32f071cx6.json | 9 ++ targets/py32f071cx6.ld | 9 ++ targets/py32f071cx8.json | 9 ++ targets/py32f071cx8.ld | 9 ++ targets/py32f071cx9.json | 9 ++ targets/py32f071cx9.ld | 9 ++ targets/py32f071cxb.json | 9 ++ targets/py32f071cxb.ld | 9 ++ targets/py32f071cxx.json | 11 ++ targets/py32f071ex6.json | 9 ++ targets/py32f071ex6.ld | 9 ++ targets/py32f071ex8.json | 9 ++ targets/py32f071ex8.ld | 9 ++ targets/py32f071ex9.json | 9 ++ targets/py32f071ex9.ld | 9 ++ targets/py32f071exb.json | 9 ++ targets/py32f071exb.ld | 9 ++ targets/py32f071exx.json | 11 ++ targets/py32f071x6.json | 9 ++ targets/py32f071x6.ld | 9 ++ targets/py32f071x8.json | 9 ++ targets/py32f071x8.ld | 9 ++ targets/py32f071x9.json | 9 ++ targets/py32f071x9.ld | 9 ++ targets/py32f071xb.json | 9 ++ targets/py32f071xb.ld | 9 ++ targets/py32f071xx.json | 11 ++ targets/py32f072cx6.json | 9 ++ targets/py32f072cx6.ld | 9 ++ targets/py32f072cx8.json | 9 ++ targets/py32f072cx8.ld | 9 ++ targets/py32f072cx9.json | 9 ++ targets/py32f072cx9.ld | 9 ++ targets/py32f072cxb.json | 9 ++ targets/py32f072cxb.ld | 9 ++ targets/py32f072cxx.json | 11 ++ targets/py32f072ex6.json | 9 ++ targets/py32f072ex6.ld | 9 ++ targets/py32f072ex8.json | 9 ++ targets/py32f072ex8.ld | 9 ++ targets/py32f072ex9.json | 9 ++ targets/py32f072ex9.ld | 9 ++ targets/py32f072exb.json | 9 ++ targets/py32f072exb.ld | 9 ++ targets/py32f072exx.json | 11 ++ targets/py32f072x6.json | 9 ++ targets/py32f072x6.ld | 9 ++ targets/py32f072x8.json | 9 ++ targets/py32f072x8.ld | 9 ++ targets/py32f072x9.json | 9 ++ targets/py32f072x9.ld | 9 ++ targets/py32f072xb.json | 9 ++ targets/py32f072xb.ld | 9 ++ targets/py32f072xx.json | 11 ++ targets/py32f403xb.json | 9 ++ targets/py32f403xb.ld | 9 ++ targets/py32f403xc.json | 9 ++ targets/py32f403xc.ld | 9 ++ targets/py32f403xd.json | 9 ++ targets/py32f403xd.ld | 9 ++ targets/py32f403xx.json | 11 ++ targets/py32f410xb.json | 9 ++ targets/py32f410xb.ld | 9 ++ targets/py32f410xx.json | 11 ++ targets/py32l020x5.json | 9 ++ targets/py32l020x5.ld | 9 ++ targets/py32l020xx.json | 12 ++ targets/py32l090xb.json | 9 ++ targets/py32l090xb.ld | 9 ++ targets/py32l090xc.json | 9 ++ targets/py32l090xc.ld | 9 ++ targets/py32l090xx.json | 11 ++ targets/py32m010x5.json | 9 ++ targets/py32m010x5.ld | 9 ++ targets/py32m010xx.json | 12 ++ targets/py32m020x6.json | 9 ++ targets/py32m020x6.ld | 9 ++ targets/py32m020xx.json | 11 ++ targets/py32m030x8.json | 9 ++ targets/py32m030x8.ld | 9 ++ targets/py32m030xx.json | 11 ++ targets/py32m031x8.json | 9 ++ targets/py32m031x8.ld | 9 ++ targets/py32m031xx.json | 11 ++ targets/py32m070cxb.json | 9 ++ targets/py32m070cxb.ld | 9 ++ targets/py32m070cxx.json | 11 ++ targets/py32m070xb.json | 9 ++ targets/py32m070xb.ld | 9 ++ targets/py32m070xx.json | 11 ++ targets/py32md310x8.json | 9 ++ targets/py32md310x8.ld | 9 ++ targets/py32md310xx.json | 11 ++ targets/py32md320x8.json | 9 ++ targets/py32md320x8.ld | 9 ++ targets/py32md320xx.json | 11 ++ targets/py32md410x8.json | 9 ++ targets/py32md410x8.ld | 9 ++ targets/py32md410xx.json | 11 ++ targets/py32md420x8.json | 9 ++ targets/py32md420x8.ld | 9 ++ targets/py32md420xx.json | 11 ++ targets/py32md430x8.json | 9 ++ targets/py32md430x8.ld | 9 ++ targets/py32md430xx.json | 11 ++ targets/py32t020bx5.json | 9 ++ targets/py32t020bx5.ld | 9 ++ targets/py32t020bx6.json | 9 ++ targets/py32t020bx6.ld | 9 ++ targets/py32t020x5.json | 9 ++ targets/py32t020x5.ld | 9 ++ targets/py32t020x6.json | 9 ++ targets/py32t020x6.ld | 9 ++ targets/py32t020xx.json | 11 ++ targets/py32t090xb.json | 9 ++ targets/py32t090xb.ld | 9 ++ targets/py32t090xc.json | 9 ++ targets/py32t090xc.ld | 9 ++ targets/py32t090xx.json | 11 ++ targets/py32t092xc.json | 9 ++ targets/py32t092xc.ld | 9 ++ targets/py32t092xx.json | 11 ++ tools/gen-device-svd/gen-device-svd.go | 6 +- tools/gen-py32-targets/README.md | 38 +++++ tools/gen-py32-targets/devices.csv | 88 +++++++++++ tools/gen-py32-targets/main.go | 202 +++++++++++++++++++++++++ tools/gen-py32-targets/main_test.go | 100 ++++++++++++ 206 files changed, 2344 insertions(+), 18 deletions(-) create mode 100644 targets/py32-m4.json create mode 100644 targets/py32e407xc.json create mode 100644 targets/py32e407xc.ld create mode 100644 targets/py32e407xd.json create mode 100644 targets/py32e407xd.ld create mode 100644 targets/py32e407xe.json create mode 100644 targets/py32e407xe.ld create mode 100644 targets/py32e407xx.json create mode 100644 targets/py32f001cx4.json create mode 100644 targets/py32f001cx4.ld create mode 100644 targets/py32f001cxx.json create mode 100644 targets/py32f001xx.json create mode 100644 targets/py32f002axx.json create mode 100644 targets/py32f002bxx.json create mode 100644 targets/py32f002cx5.json create mode 100644 targets/py32f002cx5.ld create mode 100644 targets/py32f002cxx.json create mode 100644 targets/py32f002xx2.json create mode 100644 targets/py32f002xx2.ld create mode 100644 targets/py32f002xx4.json create mode 100644 targets/py32f002xx4.ld create mode 100644 targets/py32f002xx5.json create mode 100644 targets/py32f002xx5.ld create mode 100644 targets/py32f002xxx.json create mode 100644 targets/py32f002zx4.json create mode 100644 targets/py32f002zx4.ld create mode 100644 targets/py32f002zxx.json create mode 100644 targets/py32f003xx.json create mode 100644 targets/py32f021x8.json create mode 100644 targets/py32f021x8.ld create mode 100644 targets/py32f021xx.json create mode 100644 targets/py32f030xx.json create mode 100644 targets/py32f031x4.json create mode 100644 targets/py32f031x4.ld create mode 100644 targets/py32f031x6.json create mode 100644 targets/py32f031x6.ld create mode 100644 targets/py32f031x7.json create mode 100644 targets/py32f031x7.ld create mode 100644 targets/py32f031x8.json create mode 100644 targets/py32f031x8.ld create mode 100644 targets/py32f031xx.json create mode 100644 targets/py32f032x8.json create mode 100644 targets/py32f032x8.ld create mode 100644 targets/py32f032xx.json create mode 100644 targets/py32f040cx6.json create mode 100644 targets/py32f040cx6.ld create mode 100644 targets/py32f040cx8.json create mode 100644 targets/py32f040cx8.ld create mode 100644 targets/py32f040cx9.json create mode 100644 targets/py32f040cx9.ld create mode 100644 targets/py32f040cxb.json create mode 100644 targets/py32f040cxb.ld create mode 100644 targets/py32f040cxx.json create mode 100644 targets/py32f040epxb.json create mode 100644 targets/py32f040epxb.ld create mode 100644 targets/py32f040epxx.json create mode 100644 targets/py32f040ex6.json create mode 100644 targets/py32f040ex6.ld create mode 100644 targets/py32f040ex8.json create mode 100644 targets/py32f040ex8.ld create mode 100644 targets/py32f040ex9.json create mode 100644 targets/py32f040ex9.ld create mode 100644 targets/py32f040exb.json create mode 100644 targets/py32f040exb.ld create mode 100644 targets/py32f040exx.json create mode 100644 targets/py32f040x6.json create mode 100644 targets/py32f040x6.ld create mode 100644 targets/py32f040x8.json create mode 100644 targets/py32f040x8.ld create mode 100644 targets/py32f040x9.json create mode 100644 targets/py32f040x9.ld create mode 100644 targets/py32f040xb.json create mode 100644 targets/py32f040xb.ld create mode 100644 targets/py32f040xx.json create mode 100644 targets/py32f071cx6.json create mode 100644 targets/py32f071cx6.ld create mode 100644 targets/py32f071cx8.json create mode 100644 targets/py32f071cx8.ld create mode 100644 targets/py32f071cx9.json create mode 100644 targets/py32f071cx9.ld create mode 100644 targets/py32f071cxb.json create mode 100644 targets/py32f071cxb.ld create mode 100644 targets/py32f071cxx.json create mode 100644 targets/py32f071ex6.json create mode 100644 targets/py32f071ex6.ld create mode 100644 targets/py32f071ex8.json create mode 100644 targets/py32f071ex8.ld create mode 100644 targets/py32f071ex9.json create mode 100644 targets/py32f071ex9.ld create mode 100644 targets/py32f071exb.json create mode 100644 targets/py32f071exb.ld create mode 100644 targets/py32f071exx.json create mode 100644 targets/py32f071x6.json create mode 100644 targets/py32f071x6.ld create mode 100644 targets/py32f071x8.json create mode 100644 targets/py32f071x8.ld create mode 100644 targets/py32f071x9.json create mode 100644 targets/py32f071x9.ld create mode 100644 targets/py32f071xb.json create mode 100644 targets/py32f071xb.ld create mode 100644 targets/py32f071xx.json create mode 100644 targets/py32f072cx6.json create mode 100644 targets/py32f072cx6.ld create mode 100644 targets/py32f072cx8.json create mode 100644 targets/py32f072cx8.ld create mode 100644 targets/py32f072cx9.json create mode 100644 targets/py32f072cx9.ld create mode 100644 targets/py32f072cxb.json create mode 100644 targets/py32f072cxb.ld create mode 100644 targets/py32f072cxx.json create mode 100644 targets/py32f072ex6.json create mode 100644 targets/py32f072ex6.ld create mode 100644 targets/py32f072ex8.json create mode 100644 targets/py32f072ex8.ld create mode 100644 targets/py32f072ex9.json create mode 100644 targets/py32f072ex9.ld create mode 100644 targets/py32f072exb.json create mode 100644 targets/py32f072exb.ld create mode 100644 targets/py32f072exx.json create mode 100644 targets/py32f072x6.json create mode 100644 targets/py32f072x6.ld create mode 100644 targets/py32f072x8.json create mode 100644 targets/py32f072x8.ld create mode 100644 targets/py32f072x9.json create mode 100644 targets/py32f072x9.ld create mode 100644 targets/py32f072xb.json create mode 100644 targets/py32f072xb.ld create mode 100644 targets/py32f072xx.json create mode 100644 targets/py32f403xb.json create mode 100644 targets/py32f403xb.ld create mode 100644 targets/py32f403xc.json create mode 100644 targets/py32f403xc.ld create mode 100644 targets/py32f403xd.json create mode 100644 targets/py32f403xd.ld create mode 100644 targets/py32f403xx.json create mode 100644 targets/py32f410xb.json create mode 100644 targets/py32f410xb.ld create mode 100644 targets/py32f410xx.json create mode 100644 targets/py32l020x5.json create mode 100644 targets/py32l020x5.ld create mode 100644 targets/py32l020xx.json create mode 100644 targets/py32l090xb.json create mode 100644 targets/py32l090xb.ld create mode 100644 targets/py32l090xc.json create mode 100644 targets/py32l090xc.ld create mode 100644 targets/py32l090xx.json create mode 100644 targets/py32m010x5.json create mode 100644 targets/py32m010x5.ld create mode 100644 targets/py32m010xx.json create mode 100644 targets/py32m020x6.json create mode 100644 targets/py32m020x6.ld create mode 100644 targets/py32m020xx.json create mode 100644 targets/py32m030x8.json create mode 100644 targets/py32m030x8.ld create mode 100644 targets/py32m030xx.json create mode 100644 targets/py32m031x8.json create mode 100644 targets/py32m031x8.ld create mode 100644 targets/py32m031xx.json create mode 100644 targets/py32m070cxb.json create mode 100644 targets/py32m070cxb.ld create mode 100644 targets/py32m070cxx.json create mode 100644 targets/py32m070xb.json create mode 100644 targets/py32m070xb.ld create mode 100644 targets/py32m070xx.json create mode 100644 targets/py32md310x8.json create mode 100644 targets/py32md310x8.ld create mode 100644 targets/py32md310xx.json create mode 100644 targets/py32md320x8.json create mode 100644 targets/py32md320x8.ld create mode 100644 targets/py32md320xx.json create mode 100644 targets/py32md410x8.json create mode 100644 targets/py32md410x8.ld create mode 100644 targets/py32md410xx.json create mode 100644 targets/py32md420x8.json create mode 100644 targets/py32md420x8.ld create mode 100644 targets/py32md420xx.json create mode 100644 targets/py32md430x8.json create mode 100644 targets/py32md430x8.ld create mode 100644 targets/py32md430xx.json create mode 100644 targets/py32t020bx5.json create mode 100644 targets/py32t020bx5.ld create mode 100644 targets/py32t020bx6.json create mode 100644 targets/py32t020bx6.ld create mode 100644 targets/py32t020x5.json create mode 100644 targets/py32t020x5.ld create mode 100644 targets/py32t020x6.json create mode 100644 targets/py32t020x6.ld create mode 100644 targets/py32t020xx.json create mode 100644 targets/py32t090xb.json create mode 100644 targets/py32t090xb.ld create mode 100644 targets/py32t090xc.json create mode 100644 targets/py32t090xc.ld create mode 100644 targets/py32t090xx.json create mode 100644 targets/py32t092xc.json create mode 100644 targets/py32t092xc.ld create mode 100644 targets/py32t092xx.json create mode 100644 tools/gen-py32-targets/README.md create mode 100644 tools/gen-py32-targets/devices.csv create mode 100644 tools/gen-py32-targets/main.go create mode 100644 tools/gen-py32-targets/main_test.go diff --git a/compileopts/target_test.go b/compileopts/target_test.go index 315ccf4e49..653f116fe2 100644 --- a/compileopts/target_test.go +++ b/compileopts/target_test.go @@ -1,8 +1,10 @@ package compileopts import ( + "encoding/csv" "errors" "io/fs" + "os" "reflect" "testing" ) @@ -54,6 +56,38 @@ func TestLoadTarget_InheritableOnlyTargetStillLoadable(t *testing.T) { } } +func TestLoadPY32ConcreteTargets(t *testing.T) { + file, err := os.Open("../tools/gen-py32-targets/devices.csv") + if err != nil { + t.Fatal(err) + } + defer file.Close() + + records, err := csv.NewReader(file).ReadAll() + if err != nil { + t.Fatal(err) + } + for _, record := range records[1:] { + part, core := record[0], record[2] + t.Run(part, func(t *testing.T) { + spec, err := LoadTarget(&Options{Target: part}) + if err != nil { + t.Fatal(err) + } + if spec.LinkerScript == "" { + t.Error("concrete target has no linker script") + } + wantCPU := "cortex-m0plus" + if core == "m4" { + wantCPU = "cortex-m4" + } + if spec.CPU != wantCPU { + t.Errorf("CPU is %q, want %q", spec.CPU, wantCPU) + } + }) + } +} + func TestOverrideProperties(t *testing.T) { baseAutoStackSize := true base := &TargetSpec{ diff --git a/lib/py32-svd b/lib/py32-svd index cf204623eb..06814c5eb9 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit cf204623eb20469914688563f748dc8b4a63cf65 +Subproject commit 06814c5eb9851af49c05e17b6f0cdfc97dfada72 diff --git a/make/gen-device.mk b/make/gen-device.mk index 8a777e4d5e..9f3c5cf972 100644 --- a/make/gen-device.mk +++ b/make/gen-device.mk @@ -2,7 +2,7 @@ .PHONY: gen-device gen-device-avr gen-device-esp gen-device-nrf gen-device-sam \ gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp \ - gen-device-stm32 gen-device-renesas gen-device-py32 + gen-device-stm32 gen-device-renesas gen-device-py32 gen-target-py32 gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp gen-device-py32 ## Generate microcontroller-specific sources ifneq ($(RENESAS), 0) @@ -62,3 +62,6 @@ gen-device-renesas: build/gen-device-svd gen-device-py32: build/gen-device-svd ./build/gen-device-svd -source=https://github.com/tinygo-org/py32-svd lib/py32-svd/svd src/device/py32/ GO111MODULE=off $(GO) fmt ./src/device/py32 + +gen-target-py32: ## Generate PY32 target and linker definitions + $(GO) run ./tools/gen-py32-targets diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 0409411e52..cd5280dd47 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -145,23 +145,27 @@ const ( ) const PinInput PinMode = PinInputFloating +// Puya's raw SVDs define these fields and masks but do not provide their +// enumerated values. These encodings are shared by the supported PY32 parts. const ( - gpioModeInput = py32.GPIO_MODER_MODE0_Input - gpioModeOutput = py32.GPIO_MODER_MODE0_Output - gpioModeAlternate = py32.GPIO_MODER_MODE0_Alternate - gpioModeAnalog = py32.GPIO_MODER_MODE0_Analog + gpioModeInput = 0 + gpioModeOutput = 1 + gpioModeAlternate = 2 + gpioModeAnalog = 3 gpioModeMask = py32.GPIO_MODER_MODE0_Msk - gpioPullFloating = py32.GPIO_PUPDR_PUPD0_Floating - gpioPullUp = py32.GPIO_PUPDR_PUPD0_PullUp - gpioPullDown = py32.GPIO_PUPDR_PUPD0_PullDown + gpioPullFloating = 0 + gpioPullUp = 1 + gpioPullDown = 2 gpioPullMask = py32.GPIO_PUPDR_PUPD0_Msk - gpioOutputSpeedLow = py32.GPIO_OSPEEDR_OSPEED0_LowSpeed - gpioOutputSpeedMedium = py32.GPIO_OSPEEDR_OSPEED0_MediumSpeed - gpioOutputSpeedHigh = py32.GPIO_OSPEEDR_OSPEED0_HighSpeed - gpioOutputSpeedVeryHigh = py32.GPIO_OSPEEDR_OSPEED0_VeryHighSpeed + gpioOutputSpeedLow = 0 + gpioOutputSpeedMedium = 1 + gpioOutputSpeedHigh = 2 + gpioOutputSpeedVeryHigh = 3 gpioOutputSpeedMask = py32.GPIO_OSPEEDR_OSPEED0_Msk + + gpioOutputTypePushPull = 0 ) func (p Pin) getPortNumber() uint8 { @@ -210,7 +214,7 @@ func (p Pin) Configure(config PinConfig) { port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) case PinOutput: port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos) - port.OTYPER.ReplaceBits(py32.GPIO_OTYPER_OT0_PushPull, py32.GPIO_OTYPER_OT0_Msk, pos>>1) + port.OTYPER.ReplaceBits(gpioOutputTypePushPull, py32.GPIO_OTYPER_OT0_Msk, pos>>1) port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) case PinInputAnalog: port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index b29c5fe91d..965d0bc020 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -13,11 +13,14 @@ import ( var tickCounter volatile.Register64 +// Puya's raw SVDs define HSI_FS but omit its enumerated values. +const rccICSCRHSIFrequency24MHz = 4 + //export Reset_Handler func main() { preinit() - py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) + py32.RCC.SetICSCR_HSI_FS(rccICSCRHSIFrequency24MHz) ConfigureSystemTimer() machine.InitSerial() diff --git a/targets/py32-m4.json b/targets/py32-m4.json new file mode 100644 index 0000000000..1ec16f63ec --- /dev/null +++ b/targets/py32-m4.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "cortex-m4" + ], + "scheduler": "none", + "gc": "none", + "build-tags": [ + "py32" + ] +} diff --git a/targets/py32e407xc.json b/targets/py32e407xc.json new file mode 100644 index 0000000000..ab98614c32 --- /dev/null +++ b/targets/py32e407xc.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32e407xx" + ], + "build-tags": [ + "py32e407xc" + ], + "linkerscript": "targets/py32e407xc.ld" +} diff --git a/targets/py32e407xc.ld b/targets/py32e407xc.ld new file mode 100644 index 0000000000..ed238cc140 --- /dev/null +++ b/targets/py32e407xc.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1c000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32e407xd.json b/targets/py32e407xd.json new file mode 100644 index 0000000000..f32c6b494c --- /dev/null +++ b/targets/py32e407xd.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32e407xx" + ], + "build-tags": [ + "py32e407xd" + ], + "linkerscript": "targets/py32e407xd.ld" +} diff --git a/targets/py32e407xd.ld b/targets/py32e407xd.ld new file mode 100644 index 0000000000..7bead5c559 --- /dev/null +++ b/targets/py32e407xd.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x60000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32e407xe.json b/targets/py32e407xe.json new file mode 100644 index 0000000000..581cd20f06 --- /dev/null +++ b/targets/py32e407xe.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32e407xx" + ], + "build-tags": [ + "py32e407xe" + ], + "linkerscript": "targets/py32e407xe.ld" +} diff --git a/targets/py32e407xe.ld b/targets/py32e407xe.ld new file mode 100644 index 0000000000..aaa1b18201 --- /dev/null +++ b/targets/py32e407xe.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x80000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32e407xx.json b/targets/py32e407xx.json new file mode 100644 index 0000000000..5d071bdb94 --- /dev/null +++ b/targets/py32e407xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32-m4" + ], + "build-tags": [ + "py32e407xx" + ], + "extra-files": [ + "src/device/py32/py32e407xx.s" + ] +} diff --git a/targets/py32f001cx4.json b/targets/py32f001cx4.json new file mode 100644 index 0000000000..7b97a9b226 --- /dev/null +++ b/targets/py32f001cx4.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f001cxx" + ], + "build-tags": [ + "py32f001cx4" + ], + "linkerscript": "targets/py32f001cx4.ld" +} diff --git a/targets/py32f001cx4.ld b/targets/py32f001cx4.ld new file mode 100644 index 0000000000..57223aed5f --- /dev/null +++ b/targets/py32f001cx4.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json new file mode 100644 index 0000000000..4d426bc2c0 --- /dev/null +++ b/targets/py32f001cxx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f001cxx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32f001cxx.s" + ] +} diff --git a/targets/py32f001xx.json b/targets/py32f001xx.json new file mode 100644 index 0000000000..58248f3e1b --- /dev/null +++ b/targets/py32f001xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f001xx" + ], + "extra-files": [ + "src/device/py32/py32f001xx.s" + ] +} diff --git a/targets/py32f002axx.json b/targets/py32f002axx.json new file mode 100644 index 0000000000..5aa3bca284 --- /dev/null +++ b/targets/py32f002axx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002axx" + ], + "extra-files": [ + "src/device/py32/py32f002axx.s" + ] +} diff --git a/targets/py32f002bxx.json b/targets/py32f002bxx.json new file mode 100644 index 0000000000..3181a623ad --- /dev/null +++ b/targets/py32f002bxx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002bxx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32f002bxx.s" + ] +} diff --git a/targets/py32f002cx5.json b/targets/py32f002cx5.json new file mode 100644 index 0000000000..b27921f3aa --- /dev/null +++ b/targets/py32f002cx5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f002cxx" + ], + "build-tags": [ + "py32f002cx5" + ], + "linkerscript": "targets/py32f002cx5.ld" +} diff --git a/targets/py32f002cx5.ld b/targets/py32f002cx5.ld new file mode 100644 index 0000000000..8ddf5c7d92 --- /dev/null +++ b/targets/py32f002cx5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002cxx.json b/targets/py32f002cxx.json new file mode 100644 index 0000000000..84fa15b05d --- /dev/null +++ b/targets/py32f002cxx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002cxx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32f002cxx.s" + ] +} diff --git a/targets/py32f002xx2.json b/targets/py32f002xx2.json new file mode 100644 index 0000000000..8b2851e8d2 --- /dev/null +++ b/targets/py32f002xx2.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f002xxx" + ], + "build-tags": [ + "py32f002xx2" + ], + "linkerscript": "targets/py32f002xx2.ld" +} diff --git a/targets/py32f002xx2.ld b/targets/py32f002xx2.ld new file mode 100644 index 0000000000..2e1baf059c --- /dev/null +++ b/targets/py32f002xx2.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x2000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xx4.json b/targets/py32f002xx4.json new file mode 100644 index 0000000000..07aa9b6ba0 --- /dev/null +++ b/targets/py32f002xx4.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f002xxx" + ], + "build-tags": [ + "py32f002xx4" + ], + "linkerscript": "targets/py32f002xx4.ld" +} diff --git a/targets/py32f002xx4.ld b/targets/py32f002xx4.ld new file mode 100644 index 0000000000..57223aed5f --- /dev/null +++ b/targets/py32f002xx4.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xx5.json b/targets/py32f002xx5.json new file mode 100644 index 0000000000..f5eb747d80 --- /dev/null +++ b/targets/py32f002xx5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f002xxx" + ], + "build-tags": [ + "py32f002xx5" + ], + "linkerscript": "targets/py32f002xx5.ld" +} diff --git a/targets/py32f002xx5.ld b/targets/py32f002xx5.ld new file mode 100644 index 0000000000..0a5ac0125b --- /dev/null +++ b/targets/py32f002xx5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xxx.json b/targets/py32f002xxx.json new file mode 100644 index 0000000000..7f42ffa83b --- /dev/null +++ b/targets/py32f002xxx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002xxx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32f002xxx.s" + ] +} diff --git a/targets/py32f002zx4.json b/targets/py32f002zx4.json new file mode 100644 index 0000000000..f35701b51a --- /dev/null +++ b/targets/py32f002zx4.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f002zxx" + ], + "build-tags": [ + "py32f002zx4" + ], + "linkerscript": "targets/py32f002zx4.ld" +} diff --git a/targets/py32f002zx4.ld b/targets/py32f002zx4.ld new file mode 100644 index 0000000000..57223aed5f --- /dev/null +++ b/targets/py32f002zx4.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f002zxx.json b/targets/py32f002zxx.json new file mode 100644 index 0000000000..a436cc5cc8 --- /dev/null +++ b/targets/py32f002zxx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002zxx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32f002zxx.s" + ] +} diff --git a/targets/py32f003xx.json b/targets/py32f003xx.json new file mode 100644 index 0000000000..1e8aaca9d2 --- /dev/null +++ b/targets/py32f003xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f003xx" + ], + "extra-files": [ + "src/device/py32/py32f003xx.s" + ] +} diff --git a/targets/py32f021x8.json b/targets/py32f021x8.json new file mode 100644 index 0000000000..79f8bed4d1 --- /dev/null +++ b/targets/py32f021x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f021xx" + ], + "build-tags": [ + "py32f021x8" + ], + "linkerscript": "targets/py32f021x8.ld" +} diff --git a/targets/py32f021x8.ld b/targets/py32f021x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f021x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f021xx.json b/targets/py32f021xx.json new file mode 100644 index 0000000000..458103ffce --- /dev/null +++ b/targets/py32f021xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f021xx" + ], + "extra-files": [ + "src/device/py32/py32f021xx.s" + ] +} diff --git a/targets/py32f030xx.json b/targets/py32f030xx.json new file mode 100644 index 0000000000..4546792db5 --- /dev/null +++ b/targets/py32f030xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f030xx" + ], + "extra-files": [ + "src/device/py32/py32f030xx.s" + ] +} diff --git a/targets/py32f031x4.json b/targets/py32f031x4.json new file mode 100644 index 0000000000..918686a4e9 --- /dev/null +++ b/targets/py32f031x4.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f031xx" + ], + "build-tags": [ + "py32f031x4" + ], + "linkerscript": "targets/py32f031x4.ld" +} diff --git a/targets/py32f031x4.ld b/targets/py32f031x4.ld new file mode 100644 index 0000000000..5b4e711e97 --- /dev/null +++ b/targets/py32f031x4.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x6.json b/targets/py32f031x6.json new file mode 100644 index 0000000000..a7c1ea0728 --- /dev/null +++ b/targets/py32f031x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f031xx" + ], + "build-tags": [ + "py32f031x6" + ], + "linkerscript": "targets/py32f031x6.ld" +} diff --git a/targets/py32f031x6.ld b/targets/py32f031x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f031x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x7.json b/targets/py32f031x7.json new file mode 100644 index 0000000000..b4e5ce3962 --- /dev/null +++ b/targets/py32f031x7.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f031xx" + ], + "build-tags": [ + "py32f031x7" + ], + "linkerscript": "targets/py32f031x7.ld" +} diff --git a/targets/py32f031x7.ld b/targets/py32f031x7.ld new file mode 100644 index 0000000000..50b0ef43be --- /dev/null +++ b/targets/py32f031x7.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0xc000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x8.json b/targets/py32f031x8.json new file mode 100644 index 0000000000..c60ca0a713 --- /dev/null +++ b/targets/py32f031x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f031xx" + ], + "build-tags": [ + "py32f031x8" + ], + "linkerscript": "targets/py32f031x8.ld" +} diff --git a/targets/py32f031x8.ld b/targets/py32f031x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f031x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f031xx.json b/targets/py32f031xx.json new file mode 100644 index 0000000000..ea27648d72 --- /dev/null +++ b/targets/py32f031xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f031xx" + ], + "extra-files": [ + "src/device/py32/py32f031xx.s" + ] +} diff --git a/targets/py32f032x8.json b/targets/py32f032x8.json new file mode 100644 index 0000000000..372973c077 --- /dev/null +++ b/targets/py32f032x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f032xx" + ], + "build-tags": [ + "py32f032x8" + ], + "linkerscript": "targets/py32f032x8.ld" +} diff --git a/targets/py32f032x8.ld b/targets/py32f032x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f032x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f032xx.json b/targets/py32f032xx.json new file mode 100644 index 0000000000..be4cc0c5da --- /dev/null +++ b/targets/py32f032xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f032xx" + ], + "extra-files": [ + "src/device/py32/py32f032xx.s" + ] +} diff --git a/targets/py32f040cx6.json b/targets/py32f040cx6.json new file mode 100644 index 0000000000..a622d5f0c6 --- /dev/null +++ b/targets/py32f040cx6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040cxx" + ], + "build-tags": [ + "py32f040cx6" + ], + "linkerscript": "targets/py32f040cx6.ld" +} diff --git a/targets/py32f040cx6.ld b/targets/py32f040cx6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f040cx6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cx8.json b/targets/py32f040cx8.json new file mode 100644 index 0000000000..4f3eecbdc2 --- /dev/null +++ b/targets/py32f040cx8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040cxx" + ], + "build-tags": [ + "py32f040cx8" + ], + "linkerscript": "targets/py32f040cx8.ld" +} diff --git a/targets/py32f040cx8.ld b/targets/py32f040cx8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f040cx8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cx9.json b/targets/py32f040cx9.json new file mode 100644 index 0000000000..32cc3e3dfa --- /dev/null +++ b/targets/py32f040cx9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040cxx" + ], + "build-tags": [ + "py32f040cx9" + ], + "linkerscript": "targets/py32f040cx9.ld" +} diff --git a/targets/py32f040cx9.ld b/targets/py32f040cx9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f040cx9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cxb.json b/targets/py32f040cxb.json new file mode 100644 index 0000000000..2b356c4f7c --- /dev/null +++ b/targets/py32f040cxb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040cxx" + ], + "build-tags": [ + "py32f040cxb" + ], + "linkerscript": "targets/py32f040cxb.ld" +} diff --git a/targets/py32f040cxb.ld b/targets/py32f040cxb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f040cxb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cxx.json b/targets/py32f040cxx.json new file mode 100644 index 0000000000..119dae0b17 --- /dev/null +++ b/targets/py32f040cxx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f040cxx" + ], + "extra-files": [ + "src/device/py32/py32f040cxx.s" + ] +} diff --git a/targets/py32f040epxb.json b/targets/py32f040epxb.json new file mode 100644 index 0000000000..a724082745 --- /dev/null +++ b/targets/py32f040epxb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040epxx" + ], + "build-tags": [ + "py32f040epxb" + ], + "linkerscript": "targets/py32f040epxb.ld" +} diff --git a/targets/py32f040epxb.ld b/targets/py32f040epxb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f040epxb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040epxx.json b/targets/py32f040epxx.json new file mode 100644 index 0000000000..63886e3788 --- /dev/null +++ b/targets/py32f040epxx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f040epxx" + ], + "extra-files": [ + "src/device/py32/py32f040epxx.s" + ] +} diff --git a/targets/py32f040ex6.json b/targets/py32f040ex6.json new file mode 100644 index 0000000000..a2d15f3ac3 --- /dev/null +++ b/targets/py32f040ex6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040exx" + ], + "build-tags": [ + "py32f040ex6" + ], + "linkerscript": "targets/py32f040ex6.ld" +} diff --git a/targets/py32f040ex6.ld b/targets/py32f040ex6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f040ex6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040ex8.json b/targets/py32f040ex8.json new file mode 100644 index 0000000000..200780bad7 --- /dev/null +++ b/targets/py32f040ex8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040exx" + ], + "build-tags": [ + "py32f040ex8" + ], + "linkerscript": "targets/py32f040ex8.ld" +} diff --git a/targets/py32f040ex8.ld b/targets/py32f040ex8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f040ex8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040ex9.json b/targets/py32f040ex9.json new file mode 100644 index 0000000000..11d893870f --- /dev/null +++ b/targets/py32f040ex9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040exx" + ], + "build-tags": [ + "py32f040ex9" + ], + "linkerscript": "targets/py32f040ex9.ld" +} diff --git a/targets/py32f040ex9.ld b/targets/py32f040ex9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f040ex9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040exb.json b/targets/py32f040exb.json new file mode 100644 index 0000000000..50f20d7ea4 --- /dev/null +++ b/targets/py32f040exb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040exx" + ], + "build-tags": [ + "py32f040exb" + ], + "linkerscript": "targets/py32f040exb.ld" +} diff --git a/targets/py32f040exb.ld b/targets/py32f040exb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f040exb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040exx.json b/targets/py32f040exx.json new file mode 100644 index 0000000000..6188ddfdb5 --- /dev/null +++ b/targets/py32f040exx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f040exx" + ], + "extra-files": [ + "src/device/py32/py32f040exx.s" + ] +} diff --git a/targets/py32f040x6.json b/targets/py32f040x6.json new file mode 100644 index 0000000000..9d2d184c36 --- /dev/null +++ b/targets/py32f040x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040xx" + ], + "build-tags": [ + "py32f040x6" + ], + "linkerscript": "targets/py32f040x6.ld" +} diff --git a/targets/py32f040x6.ld b/targets/py32f040x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f040x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040x8.json b/targets/py32f040x8.json new file mode 100644 index 0000000000..f9ca8454d6 --- /dev/null +++ b/targets/py32f040x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040xx" + ], + "build-tags": [ + "py32f040x8" + ], + "linkerscript": "targets/py32f040x8.ld" +} diff --git a/targets/py32f040x8.ld b/targets/py32f040x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f040x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040x9.json b/targets/py32f040x9.json new file mode 100644 index 0000000000..26a29f6594 --- /dev/null +++ b/targets/py32f040x9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040xx" + ], + "build-tags": [ + "py32f040x9" + ], + "linkerscript": "targets/py32f040x9.ld" +} diff --git a/targets/py32f040x9.ld b/targets/py32f040x9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f040x9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040xb.json b/targets/py32f040xb.json new file mode 100644 index 0000000000..032fc67f72 --- /dev/null +++ b/targets/py32f040xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f040xx" + ], + "build-tags": [ + "py32f040xb" + ], + "linkerscript": "targets/py32f040xb.ld" +} diff --git a/targets/py32f040xb.ld b/targets/py32f040xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f040xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f040xx.json b/targets/py32f040xx.json new file mode 100644 index 0000000000..124c4d99ef --- /dev/null +++ b/targets/py32f040xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f040xx" + ], + "extra-files": [ + "src/device/py32/py32f040xx.s" + ] +} diff --git a/targets/py32f071cx6.json b/targets/py32f071cx6.json new file mode 100644 index 0000000000..427e70c01a --- /dev/null +++ b/targets/py32f071cx6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071cxx" + ], + "build-tags": [ + "py32f071cx6" + ], + "linkerscript": "targets/py32f071cx6.ld" +} diff --git a/targets/py32f071cx6.ld b/targets/py32f071cx6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f071cx6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cx8.json b/targets/py32f071cx8.json new file mode 100644 index 0000000000..9d9a010d3a --- /dev/null +++ b/targets/py32f071cx8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071cxx" + ], + "build-tags": [ + "py32f071cx8" + ], + "linkerscript": "targets/py32f071cx8.ld" +} diff --git a/targets/py32f071cx8.ld b/targets/py32f071cx8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f071cx8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cx9.json b/targets/py32f071cx9.json new file mode 100644 index 0000000000..8e5199aa23 --- /dev/null +++ b/targets/py32f071cx9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071cxx" + ], + "build-tags": [ + "py32f071cx9" + ], + "linkerscript": "targets/py32f071cx9.ld" +} diff --git a/targets/py32f071cx9.ld b/targets/py32f071cx9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f071cx9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cxb.json b/targets/py32f071cxb.json new file mode 100644 index 0000000000..ef115b3847 --- /dev/null +++ b/targets/py32f071cxb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071cxx" + ], + "build-tags": [ + "py32f071cxb" + ], + "linkerscript": "targets/py32f071cxb.ld" +} diff --git a/targets/py32f071cxb.ld b/targets/py32f071cxb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f071cxb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cxx.json b/targets/py32f071cxx.json new file mode 100644 index 0000000000..0f750f1970 --- /dev/null +++ b/targets/py32f071cxx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f071cxx" + ], + "extra-files": [ + "src/device/py32/py32f071cxx.s" + ] +} diff --git a/targets/py32f071ex6.json b/targets/py32f071ex6.json new file mode 100644 index 0000000000..f91d3e0506 --- /dev/null +++ b/targets/py32f071ex6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071exx" + ], + "build-tags": [ + "py32f071ex6" + ], + "linkerscript": "targets/py32f071ex6.ld" +} diff --git a/targets/py32f071ex6.ld b/targets/py32f071ex6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f071ex6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071ex8.json b/targets/py32f071ex8.json new file mode 100644 index 0000000000..8bd64ad760 --- /dev/null +++ b/targets/py32f071ex8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071exx" + ], + "build-tags": [ + "py32f071ex8" + ], + "linkerscript": "targets/py32f071ex8.ld" +} diff --git a/targets/py32f071ex8.ld b/targets/py32f071ex8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f071ex8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071ex9.json b/targets/py32f071ex9.json new file mode 100644 index 0000000000..0364ac1607 --- /dev/null +++ b/targets/py32f071ex9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071exx" + ], + "build-tags": [ + "py32f071ex9" + ], + "linkerscript": "targets/py32f071ex9.ld" +} diff --git a/targets/py32f071ex9.ld b/targets/py32f071ex9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f071ex9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071exb.json b/targets/py32f071exb.json new file mode 100644 index 0000000000..50f21c7e85 --- /dev/null +++ b/targets/py32f071exb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071exx" + ], + "build-tags": [ + "py32f071exb" + ], + "linkerscript": "targets/py32f071exb.ld" +} diff --git a/targets/py32f071exb.ld b/targets/py32f071exb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f071exb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071exx.json b/targets/py32f071exx.json new file mode 100644 index 0000000000..c214dcc46d --- /dev/null +++ b/targets/py32f071exx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f071exx" + ], + "extra-files": [ + "src/device/py32/py32f071exx.s" + ] +} diff --git a/targets/py32f071x6.json b/targets/py32f071x6.json new file mode 100644 index 0000000000..122b9bd804 --- /dev/null +++ b/targets/py32f071x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071xx" + ], + "build-tags": [ + "py32f071x6" + ], + "linkerscript": "targets/py32f071x6.ld" +} diff --git a/targets/py32f071x6.ld b/targets/py32f071x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f071x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071x8.json b/targets/py32f071x8.json new file mode 100644 index 0000000000..e98caa23bf --- /dev/null +++ b/targets/py32f071x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071xx" + ], + "build-tags": [ + "py32f071x8" + ], + "linkerscript": "targets/py32f071x8.ld" +} diff --git a/targets/py32f071x8.ld b/targets/py32f071x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f071x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071x9.json b/targets/py32f071x9.json new file mode 100644 index 0000000000..066350d3e0 --- /dev/null +++ b/targets/py32f071x9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071xx" + ], + "build-tags": [ + "py32f071x9" + ], + "linkerscript": "targets/py32f071x9.ld" +} diff --git a/targets/py32f071x9.ld b/targets/py32f071x9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f071x9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071xb.json b/targets/py32f071xb.json new file mode 100644 index 0000000000..3425898190 --- /dev/null +++ b/targets/py32f071xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f071xx" + ], + "build-tags": [ + "py32f071xb" + ], + "linkerscript": "targets/py32f071xb.ld" +} diff --git a/targets/py32f071xb.ld b/targets/py32f071xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f071xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f071xx.json b/targets/py32f071xx.json new file mode 100644 index 0000000000..f35bffac22 --- /dev/null +++ b/targets/py32f071xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f071xx" + ], + "extra-files": [ + "src/device/py32/py32f071xx.s" + ] +} diff --git a/targets/py32f072cx6.json b/targets/py32f072cx6.json new file mode 100644 index 0000000000..65c61eac72 --- /dev/null +++ b/targets/py32f072cx6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072cxx" + ], + "build-tags": [ + "py32f072cx6" + ], + "linkerscript": "targets/py32f072cx6.ld" +} diff --git a/targets/py32f072cx6.ld b/targets/py32f072cx6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f072cx6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cx8.json b/targets/py32f072cx8.json new file mode 100644 index 0000000000..3c132f8981 --- /dev/null +++ b/targets/py32f072cx8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072cxx" + ], + "build-tags": [ + "py32f072cx8" + ], + "linkerscript": "targets/py32f072cx8.ld" +} diff --git a/targets/py32f072cx8.ld b/targets/py32f072cx8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f072cx8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cx9.json b/targets/py32f072cx9.json new file mode 100644 index 0000000000..682c894925 --- /dev/null +++ b/targets/py32f072cx9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072cxx" + ], + "build-tags": [ + "py32f072cx9" + ], + "linkerscript": "targets/py32f072cx9.ld" +} diff --git a/targets/py32f072cx9.ld b/targets/py32f072cx9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f072cx9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cxb.json b/targets/py32f072cxb.json new file mode 100644 index 0000000000..975b5a9cfe --- /dev/null +++ b/targets/py32f072cxb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072cxx" + ], + "build-tags": [ + "py32f072cxb" + ], + "linkerscript": "targets/py32f072cxb.ld" +} diff --git a/targets/py32f072cxb.ld b/targets/py32f072cxb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f072cxb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cxx.json b/targets/py32f072cxx.json new file mode 100644 index 0000000000..b637a59c29 --- /dev/null +++ b/targets/py32f072cxx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f072cxx" + ], + "extra-files": [ + "src/device/py32/py32f072cxx.s" + ] +} diff --git a/targets/py32f072ex6.json b/targets/py32f072ex6.json new file mode 100644 index 0000000000..7af1ea8173 --- /dev/null +++ b/targets/py32f072ex6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072exx" + ], + "build-tags": [ + "py32f072ex6" + ], + "linkerscript": "targets/py32f072ex6.ld" +} diff --git a/targets/py32f072ex6.ld b/targets/py32f072ex6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f072ex6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072ex8.json b/targets/py32f072ex8.json new file mode 100644 index 0000000000..ed5cc2018b --- /dev/null +++ b/targets/py32f072ex8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072exx" + ], + "build-tags": [ + "py32f072ex8" + ], + "linkerscript": "targets/py32f072ex8.ld" +} diff --git a/targets/py32f072ex8.ld b/targets/py32f072ex8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f072ex8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072ex9.json b/targets/py32f072ex9.json new file mode 100644 index 0000000000..b1dc83df8f --- /dev/null +++ b/targets/py32f072ex9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072exx" + ], + "build-tags": [ + "py32f072ex9" + ], + "linkerscript": "targets/py32f072ex9.ld" +} diff --git a/targets/py32f072ex9.ld b/targets/py32f072ex9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f072ex9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072exb.json b/targets/py32f072exb.json new file mode 100644 index 0000000000..c73f5dde51 --- /dev/null +++ b/targets/py32f072exb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072exx" + ], + "build-tags": [ + "py32f072exb" + ], + "linkerscript": "targets/py32f072exb.ld" +} diff --git a/targets/py32f072exb.ld b/targets/py32f072exb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f072exb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072exx.json b/targets/py32f072exx.json new file mode 100644 index 0000000000..2d8ebfc3b8 --- /dev/null +++ b/targets/py32f072exx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f072exx" + ], + "extra-files": [ + "src/device/py32/py32f072exx.s" + ] +} diff --git a/targets/py32f072x6.json b/targets/py32f072x6.json new file mode 100644 index 0000000000..e8a50ad05b --- /dev/null +++ b/targets/py32f072x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072xx" + ], + "build-tags": [ + "py32f072x6" + ], + "linkerscript": "targets/py32f072x6.ld" +} diff --git a/targets/py32f072x6.ld b/targets/py32f072x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32f072x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072x8.json b/targets/py32f072x8.json new file mode 100644 index 0000000000..4e147bdadb --- /dev/null +++ b/targets/py32f072x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072xx" + ], + "build-tags": [ + "py32f072x8" + ], + "linkerscript": "targets/py32f072x8.ld" +} diff --git a/targets/py32f072x8.ld b/targets/py32f072x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32f072x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072x9.json b/targets/py32f072x9.json new file mode 100644 index 0000000000..df2d576087 --- /dev/null +++ b/targets/py32f072x9.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072xx" + ], + "build-tags": [ + "py32f072x9" + ], + "linkerscript": "targets/py32f072x9.ld" +} diff --git a/targets/py32f072x9.ld b/targets/py32f072x9.ld new file mode 100644 index 0000000000..0294af6aa8 --- /dev/null +++ b/targets/py32f072x9.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x18000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072xb.json b/targets/py32f072xb.json new file mode 100644 index 0000000000..93d8896ec7 --- /dev/null +++ b/targets/py32f072xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f072xx" + ], + "build-tags": [ + "py32f072xb" + ], + "linkerscript": "targets/py32f072xb.ld" +} diff --git a/targets/py32f072xb.ld b/targets/py32f072xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f072xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f072xx.json b/targets/py32f072xx.json new file mode 100644 index 0000000000..7d81c6c7ca --- /dev/null +++ b/targets/py32f072xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f072xx" + ], + "extra-files": [ + "src/device/py32/py32f072xx.s" + ] +} diff --git a/targets/py32f403xb.json b/targets/py32f403xb.json new file mode 100644 index 0000000000..9b541d2b15 --- /dev/null +++ b/targets/py32f403xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f403xx" + ], + "build-tags": [ + "py32f403xb" + ], + "linkerscript": "targets/py32f403xb.ld" +} diff --git a/targets/py32f403xb.ld b/targets/py32f403xb.ld new file mode 100644 index 0000000000..bbe5cb507b --- /dev/null +++ b/targets/py32f403xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xc.json b/targets/py32f403xc.json new file mode 100644 index 0000000000..97ff2548af --- /dev/null +++ b/targets/py32f403xc.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f403xx" + ], + "build-tags": [ + "py32f403xc" + ], + "linkerscript": "targets/py32f403xc.ld" +} diff --git a/targets/py32f403xc.ld b/targets/py32f403xc.ld new file mode 100644 index 0000000000..643ff1c887 --- /dev/null +++ b/targets/py32f403xc.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xd.json b/targets/py32f403xd.json new file mode 100644 index 0000000000..d7dab345f5 --- /dev/null +++ b/targets/py32f403xd.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f403xx" + ], + "build-tags": [ + "py32f403xd" + ], + "linkerscript": "targets/py32f403xd.ld" +} diff --git a/targets/py32f403xd.ld b/targets/py32f403xd.ld new file mode 100644 index 0000000000..7a3906ed69 --- /dev/null +++ b/targets/py32f403xd.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x60000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xx.json b/targets/py32f403xx.json new file mode 100644 index 0000000000..d3b24b7c6f --- /dev/null +++ b/targets/py32f403xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32-m4" + ], + "build-tags": [ + "py32f403xx" + ], + "extra-files": [ + "src/device/py32/py32f403xx.s" + ] +} diff --git a/targets/py32f410xb.json b/targets/py32f410xb.json new file mode 100644 index 0000000000..0ba76798a8 --- /dev/null +++ b/targets/py32f410xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f410xx" + ], + "build-tags": [ + "py32f410xb" + ], + "linkerscript": "targets/py32f410xb.ld" +} diff --git a/targets/py32f410xb.ld b/targets/py32f410xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32f410xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json new file mode 100644 index 0000000000..5578e13851 --- /dev/null +++ b/targets/py32f410xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32-m4" + ], + "build-tags": [ + "py32f410xx" + ], + "extra-files": [ + "src/device/py32/py32f410xx.s" + ] +} diff --git a/targets/py32l020x5.json b/targets/py32l020x5.json new file mode 100644 index 0000000000..ebd4245743 --- /dev/null +++ b/targets/py32l020x5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32l020xx" + ], + "build-tags": [ + "py32l020x5" + ], + "linkerscript": "targets/py32l020x5.ld" +} diff --git a/targets/py32l020x5.ld b/targets/py32l020x5.ld new file mode 100644 index 0000000000..0a5ac0125b --- /dev/null +++ b/targets/py32l020x5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32l020xx.json b/targets/py32l020xx.json new file mode 100644 index 0000000000..0e6b2eb55f --- /dev/null +++ b/targets/py32l020xx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32l020xx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32l020xx.s" + ] +} diff --git a/targets/py32l090xb.json b/targets/py32l090xb.json new file mode 100644 index 0000000000..766063e5a6 --- /dev/null +++ b/targets/py32l090xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32l090xx" + ], + "build-tags": [ + "py32l090xb" + ], + "linkerscript": "targets/py32l090xb.ld" +} diff --git a/targets/py32l090xb.ld b/targets/py32l090xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32l090xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32l090xc.json b/targets/py32l090xc.json new file mode 100644 index 0000000000..d1b8c54a50 --- /dev/null +++ b/targets/py32l090xc.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32l090xx" + ], + "build-tags": [ + "py32l090xc" + ], + "linkerscript": "targets/py32l090xc.ld" +} diff --git a/targets/py32l090xc.ld b/targets/py32l090xc.ld new file mode 100644 index 0000000000..1370797646 --- /dev/null +++ b/targets/py32l090xc.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32l090xx.json b/targets/py32l090xx.json new file mode 100644 index 0000000000..4855b99d2b --- /dev/null +++ b/targets/py32l090xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32l090xx" + ], + "extra-files": [ + "src/device/py32/py32l090xx.s" + ] +} diff --git a/targets/py32m010x5.json b/targets/py32m010x5.json new file mode 100644 index 0000000000..0cdd961c21 --- /dev/null +++ b/targets/py32m010x5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m010xx" + ], + "build-tags": [ + "py32m010x5" + ], + "linkerscript": "targets/py32m010x5.ld" +} diff --git a/targets/py32m010x5.ld b/targets/py32m010x5.ld new file mode 100644 index 0000000000..0a5ac0125b --- /dev/null +++ b/targets/py32m010x5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m010xx.json b/targets/py32m010xx.json new file mode 100644 index 0000000000..7947f476a4 --- /dev/null +++ b/targets/py32m010xx.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m010xx", + "no_gpio_afrh" + ], + "extra-files": [ + "src/device/py32/py32m010xx.s" + ] +} diff --git a/targets/py32m020x6.json b/targets/py32m020x6.json new file mode 100644 index 0000000000..722e3f804f --- /dev/null +++ b/targets/py32m020x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m020xx" + ], + "build-tags": [ + "py32m020x6" + ], + "linkerscript": "targets/py32m020x6.ld" +} diff --git a/targets/py32m020x6.ld b/targets/py32m020x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32m020x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m020xx.json b/targets/py32m020xx.json new file mode 100644 index 0000000000..de327e7ae4 --- /dev/null +++ b/targets/py32m020xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m020xx" + ], + "extra-files": [ + "src/device/py32/py32m020xx.s" + ] +} diff --git a/targets/py32m030x8.json b/targets/py32m030x8.json new file mode 100644 index 0000000000..589d683124 --- /dev/null +++ b/targets/py32m030x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m030xx" + ], + "build-tags": [ + "py32m030x8" + ], + "linkerscript": "targets/py32m030x8.ld" +} diff --git a/targets/py32m030x8.ld b/targets/py32m030x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32m030x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m030xx.json b/targets/py32m030xx.json new file mode 100644 index 0000000000..bb1e547ddb --- /dev/null +++ b/targets/py32m030xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m030xx" + ], + "extra-files": [ + "src/device/py32/py32m030xx.s" + ] +} diff --git a/targets/py32m031x8.json b/targets/py32m031x8.json new file mode 100644 index 0000000000..5157d418eb --- /dev/null +++ b/targets/py32m031x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m031xx" + ], + "build-tags": [ + "py32m031x8" + ], + "linkerscript": "targets/py32m031x8.ld" +} diff --git a/targets/py32m031x8.ld b/targets/py32m031x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32m031x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m031xx.json b/targets/py32m031xx.json new file mode 100644 index 0000000000..06ee608cc4 --- /dev/null +++ b/targets/py32m031xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m031xx" + ], + "extra-files": [ + "src/device/py32/py32m031xx.s" + ] +} diff --git a/targets/py32m070cxb.json b/targets/py32m070cxb.json new file mode 100644 index 0000000000..072fbdd0cb --- /dev/null +++ b/targets/py32m070cxb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m070cxx" + ], + "build-tags": [ + "py32m070cxb" + ], + "linkerscript": "targets/py32m070cxb.ld" +} diff --git a/targets/py32m070cxb.ld b/targets/py32m070cxb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32m070cxb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m070cxx.json b/targets/py32m070cxx.json new file mode 100644 index 0000000000..99c6f0762c --- /dev/null +++ b/targets/py32m070cxx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m070cxx" + ], + "extra-files": [ + "src/device/py32/py32m070cxx.s" + ] +} diff --git a/targets/py32m070xb.json b/targets/py32m070xb.json new file mode 100644 index 0000000000..aa77d3ecc6 --- /dev/null +++ b/targets/py32m070xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32m070xx" + ], + "build-tags": [ + "py32m070xb" + ], + "linkerscript": "targets/py32m070xb.ld" +} diff --git a/targets/py32m070xb.ld b/targets/py32m070xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32m070xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32m070xx.json b/targets/py32m070xx.json new file mode 100644 index 0000000000..4c969220c2 --- /dev/null +++ b/targets/py32m070xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32m070xx" + ], + "extra-files": [ + "src/device/py32/py32m070xx.s" + ] +} diff --git a/targets/py32md310x8.json b/targets/py32md310x8.json new file mode 100644 index 0000000000..849aadc41c --- /dev/null +++ b/targets/py32md310x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32md310xx" + ], + "build-tags": [ + "py32md310x8" + ], + "linkerscript": "targets/py32md310x8.ld" +} diff --git a/targets/py32md310x8.ld b/targets/py32md310x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32md310x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32md310xx.json b/targets/py32md310xx.json new file mode 100644 index 0000000000..5ca306e773 --- /dev/null +++ b/targets/py32md310xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32md310xx" + ], + "extra-files": [ + "src/device/py32/py32md310xx.s" + ] +} diff --git a/targets/py32md320x8.json b/targets/py32md320x8.json new file mode 100644 index 0000000000..44e23ea151 --- /dev/null +++ b/targets/py32md320x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32md320xx" + ], + "build-tags": [ + "py32md320x8" + ], + "linkerscript": "targets/py32md320x8.ld" +} diff --git a/targets/py32md320x8.ld b/targets/py32md320x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32md320x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32md320xx.json b/targets/py32md320xx.json new file mode 100644 index 0000000000..4f7682b468 --- /dev/null +++ b/targets/py32md320xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32md320xx" + ], + "extra-files": [ + "src/device/py32/py32md320xx.s" + ] +} diff --git a/targets/py32md410x8.json b/targets/py32md410x8.json new file mode 100644 index 0000000000..f306e878cc --- /dev/null +++ b/targets/py32md410x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32md410xx" + ], + "build-tags": [ + "py32md410x8" + ], + "linkerscript": "targets/py32md410x8.ld" +} diff --git a/targets/py32md410x8.ld b/targets/py32md410x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32md410x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32md410xx.json b/targets/py32md410xx.json new file mode 100644 index 0000000000..e51dacf417 --- /dev/null +++ b/targets/py32md410xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32md410xx" + ], + "extra-files": [ + "src/device/py32/py32md410xx.s" + ] +} diff --git a/targets/py32md420x8.json b/targets/py32md420x8.json new file mode 100644 index 0000000000..118afda153 --- /dev/null +++ b/targets/py32md420x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32md420xx" + ], + "build-tags": [ + "py32md420x8" + ], + "linkerscript": "targets/py32md420x8.ld" +} diff --git a/targets/py32md420x8.ld b/targets/py32md420x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32md420x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32md420xx.json b/targets/py32md420xx.json new file mode 100644 index 0000000000..239c8fd08e --- /dev/null +++ b/targets/py32md420xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32md420xx" + ], + "extra-files": [ + "src/device/py32/py32md420xx.s" + ] +} diff --git a/targets/py32md430x8.json b/targets/py32md430x8.json new file mode 100644 index 0000000000..f221113892 --- /dev/null +++ b/targets/py32md430x8.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32md430xx" + ], + "build-tags": [ + "py32md430x8" + ], + "linkerscript": "targets/py32md430x8.ld" +} diff --git a/targets/py32md430x8.ld b/targets/py32md430x8.ld new file mode 100644 index 0000000000..bcf3f555b3 --- /dev/null +++ b/targets/py32md430x8.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32md430xx.json b/targets/py32md430xx.json new file mode 100644 index 0000000000..dedd024701 --- /dev/null +++ b/targets/py32md430xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32md430xx" + ], + "extra-files": [ + "src/device/py32/py32md430xx.s" + ] +} diff --git a/targets/py32t020bx5.json b/targets/py32t020bx5.json new file mode 100644 index 0000000000..dd4409ae1a --- /dev/null +++ b/targets/py32t020bx5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t020xx" + ], + "build-tags": [ + "py32t020bx5" + ], + "linkerscript": "targets/py32t020bx5.ld" +} diff --git a/targets/py32t020bx5.ld b/targets/py32t020bx5.ld new file mode 100644 index 0000000000..bf4b1999c5 --- /dev/null +++ b/targets/py32t020bx5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x5000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t020bx6.json b/targets/py32t020bx6.json new file mode 100644 index 0000000000..3a9b95cd7c --- /dev/null +++ b/targets/py32t020bx6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t020xx" + ], + "build-tags": [ + "py32t020bx6" + ], + "linkerscript": "targets/py32t020bx6.ld" +} diff --git a/targets/py32t020bx6.ld b/targets/py32t020bx6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32t020bx6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t020x5.json b/targets/py32t020x5.json new file mode 100644 index 0000000000..7e4521536d --- /dev/null +++ b/targets/py32t020x5.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t020xx" + ], + "build-tags": [ + "py32t020x5" + ], + "linkerscript": "targets/py32t020x5.ld" +} diff --git a/targets/py32t020x5.ld b/targets/py32t020x5.ld new file mode 100644 index 0000000000..bf4b1999c5 --- /dev/null +++ b/targets/py32t020x5.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x5000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t020x6.json b/targets/py32t020x6.json new file mode 100644 index 0000000000..ff9cb7c566 --- /dev/null +++ b/targets/py32t020x6.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t020xx" + ], + "build-tags": [ + "py32t020x6" + ], + "linkerscript": "targets/py32t020x6.ld" +} diff --git a/targets/py32t020x6.ld b/targets/py32t020x6.ld new file mode 100644 index 0000000000..8012cccc6c --- /dev/null +++ b/targets/py32t020x6.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t020xx.json b/targets/py32t020xx.json new file mode 100644 index 0000000000..473ec395f6 --- /dev/null +++ b/targets/py32t020xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32t020xx" + ], + "extra-files": [ + "src/device/py32/py32t020xx.s" + ] +} diff --git a/targets/py32t090xb.json b/targets/py32t090xb.json new file mode 100644 index 0000000000..66740ccde9 --- /dev/null +++ b/targets/py32t090xb.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t090xx" + ], + "build-tags": [ + "py32t090xb" + ], + "linkerscript": "targets/py32t090xb.ld" +} diff --git a/targets/py32t090xb.ld b/targets/py32t090xb.ld new file mode 100644 index 0000000000..941f23a0cc --- /dev/null +++ b/targets/py32t090xb.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x20000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t090xc.json b/targets/py32t090xc.json new file mode 100644 index 0000000000..6d640b13dc --- /dev/null +++ b/targets/py32t090xc.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t090xx" + ], + "build-tags": [ + "py32t090xc" + ], + "linkerscript": "targets/py32t090xc.ld" +} diff --git a/targets/py32t090xc.ld b/targets/py32t090xc.ld new file mode 100644 index 0000000000..1370797646 --- /dev/null +++ b/targets/py32t090xc.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t090xx.json b/targets/py32t090xx.json new file mode 100644 index 0000000000..1c94725f27 --- /dev/null +++ b/targets/py32t090xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32t090xx" + ], + "extra-files": [ + "src/device/py32/py32t090xx.s" + ] +} diff --git a/targets/py32t092xc.json b/targets/py32t092xc.json new file mode 100644 index 0000000000..816c29039f --- /dev/null +++ b/targets/py32t092xc.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32t092xx" + ], + "build-tags": [ + "py32t092xc" + ], + "linkerscript": "targets/py32t092xc.ld" +} diff --git a/targets/py32t092xc.ld b/targets/py32t092xc.ld new file mode 100644 index 0000000000..1370797646 --- /dev/null +++ b/targets/py32t092xc.ld @@ -0,0 +1,9 @@ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" diff --git a/targets/py32t092xx.json b/targets/py32t092xx.json new file mode 100644 index 0000000000..5e6d6adac5 --- /dev/null +++ b/targets/py32t092xx.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32t092xx" + ], + "extra-files": [ + "src/device/py32/py32t092xx.s" + ] +} diff --git a/tools/gen-device-svd/gen-device-svd.go b/tools/gen-device-svd/gen-device-svd.go index ef9dedff97..6c5e78ed81 100755 --- a/tools/gen-device-svd/gen-device-svd.go +++ b/tools/gen-device-svd/gen-device-svd.go @@ -668,12 +668,12 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre // try use bitRange // example string: "[20:16]" parts := strings.Split(strings.Trim(*fieldEl.BitRange, "[]"), ":") - l, err := strconv.ParseUint(parts[1], 0, 32) + l, err := strconv.ParseUint(parts[1], 10, 32) if err != nil { panic(err) } lsb = uint32(l) - m, err := strconv.ParseUint(parts[0], 0, 32) + m, err := strconv.ParseUint(parts[0], 10, 32) if err != nil { panic(err) } @@ -1281,7 +1281,7 @@ const ( {{- "\n"}} {{- end}} // Highest interrupt number on this device. - IRQ_max = {{.interruptMax}} + IRQ_max = {{.interruptMax}} ) // Pseudo function call that is replaced by the compiler with the actual diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md new file mode 100644 index 0000000000..0c70dfcd7a --- /dev/null +++ b/tools/gen-py32-targets/README.md @@ -0,0 +1,38 @@ +# PY32 target generator + +This command generates TinyGo target JSON and linker scripts for Puya PY32 +microcontrollers. Run it from the repository root: + +```sh +make gen-target-py32 +``` + +The normalized [device table](devices.csv) was derived from the `` and +`` leaves in the official Puya CMSIS-Pack PDSC files. Memory values are +the inherited default `IROM1` and `IRAM1` regions. The three PY32E407 parts have +multiple adjacent default RAM regions; their linker definitions combine those +regions into one contiguous RAM range. + +The table contains 87 concrete devices associated with 40 SVD families. The +pack also supplies `PY32F001xx.svd` without a corresponding PDSC device, so the +generator creates its family target but cannot create a concrete memory target. +Together these inputs produce family targets for all 41 available SVDs. + +Cortex-M0+ families inherit `py32`; PY32E407, PY32F403, and PY32F410 families +inherit `py32-m4`, which uses TinyGo's standard soft-float Cortex-M4 ABI. Targets +whose SVD has no `GPIO.AFRH` register receive the `no_gpio_afrh` build tag. + +Existing PY32 target files are retained for compatibility. In particular, their +established aliases and flashing commands are not regenerated. Newly generated +targets intentionally omit flashing commands because a compatible programmer +identifier has not been verified for every Puya part. + +## Machine support status + +All target definitions can be loaded independently of machine-driver support. +A minimal program currently compiles for 68 of the 87 concrete targets. The +remaining targets are E407, F001C, F002C, F032, F403, F410, L090, T020, T090, +and T092 devices whose raw SVD register layouts do not match assumptions in the +existing generic PY32 GPIO, RCC, or UART implementations. Their definitions are +included deliberately so machine support can be added without revisiting target +and linker metadata. \ No newline at end of file diff --git a/tools/gen-py32-targets/devices.csv b/tools/gen-py32-targets/devices.csv new file mode 100644 index 0000000000..4d36f38307 --- /dev/null +++ b/tools/gen-py32-targets/devices.csv @@ -0,0 +1,88 @@ +part,family,core,flash_start,flash_size,ram_start,ram_size +py32e407xc,py32e407xx,m4,0x08000000,0x40000,0x20000000,0x1c000 +py32e407xd,py32e407xx,m4,0x08000000,0x60000,0x20000000,0x24000 +py32e407xe,py32e407xx,m4,0x08000000,0x80000,0x20000000,0x24000 +py32f001cx4,py32f001cxx,m0,0x08000000,0x4000,0x20000000,0xc00 +py32f002ax5,py32f002axx,m0,0x08000000,0x5000,0x20000000,0xc00 +py32f002bx5,py32f002bxx,m0,0x08000000,0x6000,0x20000000,0xc00 +py32f002cx5,py32f002cxx,m0,0x08000000,0x8000,0x20000000,0xc00 +py32f002xx2,py32f002xxx,m0,0x08000000,0x2000,0x20000000,0xc00 +py32f002xx4,py32f002xxx,m0,0x08000000,0x4000,0x20000000,0xc00 +py32f002xx5,py32f002xxx,m0,0x08000000,0x6000,0x20000000,0xc00 +py32f002zx4,py32f002zxx,m0,0x08000000,0x4000,0x20000000,0xc00 +py32f003x4,py32f003xx,m0,0x08000000,0x4000,0x20000000,0x800 +py32f003x6,py32f003xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f003x7,py32f003xx,m0,0x08000000,0xc000,0x20000000,0x1800 +py32f003x8,py32f003xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f021x8,py32f021xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f030x4,py32f030xx,m0,0x08000000,0x4000,0x20000000,0x800 +py32f030x6,py32f030xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f030x7,py32f030xx,m0,0x08000000,0xc000,0x20000000,0x1800 +py32f030x8,py32f030xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f031x4,py32f031xx,m0,0x08000000,0x4000,0x20000000,0x800 +py32f031x6,py32f031xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f031x7,py32f031xx,m0,0x08000000,0xc000,0x20000000,0x1800 +py32f031x8,py32f031xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f032x8,py32f032xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f040cx6,py32f040cxx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f040cx8,py32f040cxx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f040cx9,py32f040cxx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f040cxb,py32f040cxx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f040epxb,py32f040epxx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f040ex6,py32f040exx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f040ex8,py32f040exx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f040ex9,py32f040exx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f040exb,py32f040exx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f040x6,py32f040xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f040x8,py32f040xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f040x9,py32f040xx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f040xb,py32f040xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f071cx6,py32f071cxx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f071cx8,py32f071cxx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f071cx9,py32f071cxx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f071cxb,py32f071cxx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f071ex6,py32f071exx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f071ex8,py32f071exx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f071ex9,py32f071exx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f071exb,py32f071exx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f071x6,py32f071xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f071x8,py32f071xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f071x9,py32f071xx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f071xb,py32f071xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f072cx6,py32f072cxx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f072cx8,py32f072cxx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f072cx9,py32f072cxx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f072cxb,py32f072cxx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f072ex6,py32f072exx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f072ex8,py32f072exx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f072ex9,py32f072exx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f072exb,py32f072exx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f072x6,py32f072xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32f072x8,py32f072xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32f072x9,py32f072xx,m0,0x08000000,0x18000,0x20000000,0x3000 +py32f072xb,py32f072xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32f403xb,py32f403xx,m4,0x08000000,0x20000,0x20000000,0x10000 +py32f403xc,py32f403xx,m4,0x08000000,0x40000,0x20000000,0x10000 +py32f403xd,py32f403xx,m4,0x08000000,0x60000,0x20000000,0x10000 +py32f410xb,py32f410xx,m4,0x08000000,0x20000,0x20000000,0x4000 +py32l020x5,py32l020xx,m0,0x08000000,0x6000,0x20000000,0xc00 +py32l090xb,py32l090xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32l090xc,py32l090xx,m0,0x08000000,0x40000,0x20000000,0x8000 +py32m010x5,py32m010xx,m0,0x08000000,0x6000,0x20000000,0xc00 +py32m020x6,py32m020xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32m030x8,py32m030xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32m031x8,py32m031xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32m070cxb,py32m070cxx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32m070xb,py32m070xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32md310x8,py32md310xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32md320x8,py32md320xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32md410x8,py32md410xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32md420x8,py32md420xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32md430x8,py32md430xx,m0,0x08000000,0x10000,0x20000000,0x2000 +py32t020bx5,py32t020xx,m0,0x08000000,0x5000,0x20000000,0x800 +py32t020bx6,py32t020xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32t020x5,py32t020xx,m0,0x08000000,0x5000,0x20000000,0x800 +py32t020x6,py32t020xx,m0,0x08000000,0x8000,0x20000000,0x1000 +py32t090xb,py32t090xx,m0,0x08000000,0x20000,0x20000000,0x4000 +py32t090xc,py32t090xx,m0,0x08000000,0x40000,0x20000000,0x8000 +py32t092xc,py32t092xx,m0,0x08000000,0x40000,0x20000000,0x8000 diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go new file mode 100644 index 0000000000..27172fd0da --- /dev/null +++ b/tools/gen-py32-targets/main.go @@ -0,0 +1,202 @@ +// Command gen-py32-targets generates PY32 target and linker definitions from +// normalized CMSIS-Pack device metadata. +package main + +import ( + "encoding/csv" + "encoding/json" + "errors" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strconv" + "strings" +) + +type device struct { + Part string + Family string + Core string + FlashStart uint64 + FlashSize uint64 + RAMStart uint64 + RAMSize uint64 +} + +type target struct { + Inherits []string `json:"inherits"` + BuildTags []string `json:"build-tags,omitempty"` + LinkerScript string `json:"linkerscript,omitempty"` + ExtraFiles []string `json:"extra-files,omitempty"` +} + +var orphanFamilies = map[string]string{ + // This SVD is present in PY32F0xx_DFP, but that pack has no matching PDSC + // device entry from which a concrete memory configuration can be derived. + "py32f001xx": "m0", +} + +var noGPIOAFRH = map[string]bool{ + "py32f001cxx": true, + "py32f002bxx": true, + "py32f002cxx": true, + "py32f002xxx": true, + "py32f002zxx": true, + "py32l020xx": true, + "py32m010xx": true, +} + +var legacyTargets = map[string]bool{ + // Keep pre-existing definitions, including established aliases and flashing + // commands. New definitions intentionally contain no flashing command. + "py32f002ax5": true, + "py32f002bx5": true, + "py32f003x4": true, + "py32f003x6": true, + "py32f003x7": true, + "py32f003x8": true, + "py32f030x4": true, + "py32f030x6": true, + "py32f030x7": true, + "py32f030x8": true, +} + +func main() { + table := flag.String("table", "tools/gen-py32-targets/devices.csv", "normalized device table") + out := flag.String("out", "targets", "target output directory") + flag.Parse() + + devices, err := readDevices(*table) + if err != nil { + fatal(err) + } + if err := generate(*out, devices); err != nil { + fatal(err) + } +} + +func fatal(err error) { + fmt.Fprintln(os.Stderr, "gen-py32-targets:", err) + os.Exit(1) +} + +func readDevices(path string) ([]device, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + reader := csv.NewReader(file) + header, err := reader.Read() + if err != nil { + return nil, err + } + wantHeader := []string{"part", "family", "core", "flash_start", "flash_size", "ram_start", "ram_size"} + if strings.Join(header, ",") != strings.Join(wantHeader, ",") { + return nil, fmt.Errorf("unexpected CSV header %q", strings.Join(header, ",")) + } + + var devices []device + seen := make(map[string]bool) + for line := 2; ; line++ { + record, err := reader.Read() + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return nil, fmt.Errorf("line %d: %w", line, err) + } + if seen[record[0]] { + return nil, fmt.Errorf("line %d: duplicate part %q", line, record[0]) + } + seen[record[0]] = true + if record[2] != "m0" && record[2] != "m4" { + return nil, fmt.Errorf("line %d: unsupported core %q", line, record[2]) + } + values := make([]uint64, 4) + for i, field := range record[3:] { + values[i], err = strconv.ParseUint(field, 0, 64) + if err != nil || values[i] == 0 { + return nil, fmt.Errorf("line %d: invalid memory value %q", line, field) + } + } + devices = append(devices, device{ + Part: record[0], Family: record[1], Core: record[2], + FlashStart: values[0], FlashSize: values[1], + RAMStart: values[2], RAMSize: values[3], + }) + } + return devices, nil +} + +func generate(out string, devices []device) error { + if err := os.MkdirAll(out, 0o755); err != nil { + return err + } + families := make(map[string]string, len(orphanFamilies)) + for name, core := range orphanFamilies { + families[name] = core + } + for _, device := range devices { + if core, ok := families[device.Family]; ok && core != device.Core { + return fmt.Errorf("family %q mixes %s and %s cores", device.Family, core, device.Core) + } + families[device.Family] = device.Core + } + + familyNames := make([]string, 0, len(families)) + for name := range families { + familyNames = append(familyNames, name) + } + sort.Strings(familyNames) + for _, family := range familyNames { + base := "py32" + if families[family] == "m4" { + base = "py32-m4" + } + tags := []string{family} + if noGPIOAFRH[family] { + tags = append(tags, "no_gpio_afrh") + } + spec := target{ + Inherits: []string{base}, + BuildTags: tags, + ExtraFiles: []string{"src/device/py32/" + family + ".s"}, + } + if err := writeJSON(filepath.Join(out, family+".json"), spec); err != nil { + return err + } + } + + for _, device := range devices { + if legacyTargets[device.Part] { + continue + } + spec := target{ + Inherits: []string{device.Family}, + BuildTags: []string{device.Part}, + LinkerScript: "targets/" + device.Part + ".ld", + } + if err := writeJSON(filepath.Join(out, device.Part+".json"), spec); err != nil { + return err + } + linker := fmt.Sprintf("MEMORY\n{\n FLASH_TEXT (rx) : ORIGIN = %#x, LENGTH = %#x\n RAM (xrw) : ORIGIN = %#x, LENGTH = %#x\n}\n\n_stack_size = 512;\n\nINCLUDE \"targets/arm.ld\"\n", device.FlashStart, device.FlashSize, device.RAMStart, device.RAMSize) + if err := os.WriteFile(filepath.Join(out, device.Part+".ld"), []byte(linker), 0o644); err != nil { + return err + } + } + return nil +} + +func writeJSON(path string, value any) error { + data, err := json.MarshalIndent(value, "", " ") + if err != nil { + return err + } + data = append(data, '\n') + return os.WriteFile(path, data, 0o644) +} diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go new file mode 100644 index 0000000000..4789154faf --- /dev/null +++ b/tools/gen-py32-targets/main_test.go @@ -0,0 +1,100 @@ +package main + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" +) + +func TestDeviceTable(t *testing.T) { + devices, err := readDevices("devices.csv") + if err != nil { + t.Fatal(err) + } + if got, want := len(devices), 87; got != want { + t.Fatalf("got %d concrete devices, want %d", got, want) + } + + families := make(map[string]bool) + for family := range orphanFamilies { + families[family] = true + } + m4 := 0 + for _, device := range devices { + families[device.Family] = true + if device.Core == "m4" { + m4++ + } + } + if got, want := len(families), 41; got != want { + t.Fatalf("got %d SVD families, want %d", got, want) + } + if got, want := m4, 7; got != want { + t.Fatalf("got %d Cortex-M4 devices, want %d", got, want) + } +} + +func TestGenerate(t *testing.T) { + devices, err := readDevices("devices.csv") + if err != nil { + t.Fatal(err) + } + out := t.TempDir() + if err := generate(out, devices); err != nil { + t.Fatal(err) + } + + entries, err := os.ReadDir(out) + if err != nil { + t.Fatal(err) + } + // 41 family JSON files plus JSON and linker files for the 77 non-legacy + // concrete targets. + if got, want := len(entries), 195; got != want { + t.Fatalf("generated %d files, want %d", got, want) + } + + checkTarget(t, filepath.Join(out, "py32e407xc.json"), "py32e407xx", "targets/py32e407xc.ld") + checkTarget(t, filepath.Join(out, "py32f001xx.json"), "py32", "") + checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "") + + data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) + if err != nil { + t.Fatal(err) + } + want := "ORIGIN = 0x20000000, LENGTH = 0x1c000" + if !contains(string(data), want) { + t.Fatalf("E407 linker script does not contain combined contiguous RAM %q", want) + } + if _, err := os.Stat(filepath.Join(out, "py32f030x8.json")); !os.IsNotExist(err) { + t.Fatalf("legacy target was generated: %v", err) + } +} + +func checkTarget(t *testing.T, path, inherited, linker string) { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var spec target + if err := json.Unmarshal(data, &spec); err != nil { + t.Fatal(err) + } + if len(spec.Inherits) != 1 || spec.Inherits[0] != inherited { + t.Errorf("%s inherits %v, want %q", path, spec.Inherits, inherited) + } + if spec.LinkerScript != linker { + t.Errorf("%s linker script is %q, want %q", path, spec.LinkerScript, linker) + } +} + +func contains(value, substring string) bool { + for i := 0; i+len(substring) <= len(value); i++ { + if value[i:i+len(substring)] == substring { + return true + } + } + return false +} From b52650c0064c12090745fd8b5941b193b49371ef Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 6 Aug 2026 00:25:10 +0200 Subject: [PATCH 37/62] Support all PY32 register layout variants --- lib/py32-svd | 2 +- src/machine/machine_py32_pin.go | 17 ++---- src/machine/machine_py32_pin_clock.go | 9 +++ src/machine/machine_py32_pin_clock_ahb.go | 10 ++++ src/machine/machine_py32_pin_clock_ahb1.go | 10 ++++ src/machine/machine_py32_pin_speed.go | 9 +++ src/machine/machine_py32_pin_speed_ospdder.go | 9 +++ src/machine/machine_py32_uart.go | 33 +++-------- src/machine/machine_py32_uart_clock.go | 10 ++++ src/machine/machine_py32_uart_clock_apb2.go | 9 +++ src/machine/machine_py32_uart_common.go | 15 +++++ src/machine/machine_py32_uart_data.go | 21 +++++++ src/machine/machine_py32_uart_data_split.go | 21 +++++++ src/machine/machine_py32_uart_interrupt.go | 14 +++++ src/machine/machine_py32_uart_no_interrupt.go | 8 +++ src/machine/machine_py32_uart_type.go | 57 +++++++++++++++++++ src/machine/machine_py32_uart_usart.go | 9 +++ .../machine_py32_uart_usart_unnumbered.go | 9 +++ src/runtime/runtime_py32.go | 7 +-- src/runtime/runtime_py32_hsi.go | 11 ++++ src/runtime/runtime_py32_hsi_none.go | 8 +++ src/runtime/runtime_py32_hsi_op.go | 9 +++ targets/py32e407xx.json | 7 ++- targets/py32f403xx.json | 5 +- targets/py32f410xx.json | 8 ++- targets/py32l090xx.json | 4 +- targets/py32t020xx.json | 3 +- targets/py32t090xx.json | 4 +- targets/py32t092xx.json | 4 +- tools/gen-py32-targets/README.md | 28 ++++++--- tools/gen-py32-targets/main.go | 51 +++++++++++++++-- tools/gen-py32-targets/main_test.go | 19 +++++++ 32 files changed, 378 insertions(+), 62 deletions(-) create mode 100644 src/machine/machine_py32_pin_clock.go create mode 100644 src/machine/machine_py32_pin_clock_ahb.go create mode 100644 src/machine/machine_py32_pin_clock_ahb1.go create mode 100644 src/machine/machine_py32_pin_speed.go create mode 100644 src/machine/machine_py32_pin_speed_ospdder.go create mode 100644 src/machine/machine_py32_uart_clock.go create mode 100644 src/machine/machine_py32_uart_clock_apb2.go create mode 100644 src/machine/machine_py32_uart_common.go create mode 100644 src/machine/machine_py32_uart_data.go create mode 100644 src/machine/machine_py32_uart_data_split.go create mode 100644 src/machine/machine_py32_uart_interrupt.go create mode 100644 src/machine/machine_py32_uart_no_interrupt.go create mode 100644 src/machine/machine_py32_uart_type.go create mode 100644 src/machine/machine_py32_uart_usart.go create mode 100644 src/machine/machine_py32_uart_usart_unnumbered.go create mode 100644 src/runtime/runtime_py32_hsi.go create mode 100644 src/runtime/runtime_py32_hsi_none.go create mode 100644 src/runtime/runtime_py32_hsi_op.go diff --git a/lib/py32-svd b/lib/py32-svd index 06814c5eb9..2de730eb83 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit 06814c5eb9851af49c05e17b6f0cdfc97dfada72 +Subproject commit 2de730eb8306f06f8d20350769dbc3986deeb3e5 diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index cd5280dd47..3f4039c7d8 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -152,18 +152,18 @@ const ( gpioModeOutput = 1 gpioModeAlternate = 2 gpioModeAnalog = 3 - gpioModeMask = py32.GPIO_MODER_MODE0_Msk + gpioModeMask = 0x3 gpioPullFloating = 0 gpioPullUp = 1 gpioPullDown = 2 - gpioPullMask = py32.GPIO_PUPDR_PUPD0_Msk + gpioPullMask = 0x3 gpioOutputSpeedLow = 0 gpioOutputSpeedMedium = 1 gpioOutputSpeedHigh = 2 gpioOutputSpeedVeryHigh = 3 - gpioOutputSpeedMask = py32.GPIO_OSPEEDR_OSPEED0_Msk + gpioOutputSpeedMask = 0x3 gpioOutputTypePushPull = 0 ) @@ -214,18 +214,13 @@ func (p Pin) Configure(config PinConfig) { port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) case PinOutput: port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos) - port.OTYPER.ReplaceBits(gpioOutputTypePushPull, py32.GPIO_OTYPER_OT0_Msk, pos>>1) - port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + port.OTYPER.ReplaceBits(gpioOutputTypePushPull, 0x1, pos>>1) + setPinOutputSpeed(port, gpioOutputSpeedHigh, pos) case PinInputAnalog: port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) case PinAlternate: port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) - port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + setPinOutputSpeed(port, gpioOutputSpeedHigh, pos) } } - -func (p Pin) enableClock() { - portNo := p.getPortNumber() - py32.RCC.IOPENR.SetBits(1 << portNo) -} diff --git a/src/machine/machine_py32_pin_clock.go b/src/machine/machine_py32_pin_clock.go new file mode 100644 index 0000000000..167b1ac8e4 --- /dev/null +++ b/src/machine/machine_py32_pin_clock.go @@ -0,0 +1,9 @@ +//go:build py32 && !py32_gpio_clock_ahb1 && !py32_gpio_clock_ahb + +package machine + +import "device/py32" + +func (p Pin) enableClock() { + py32.RCC.IOPENR.SetBits(1 << p.getPortNumber()) +} diff --git a/src/machine/machine_py32_pin_clock_ahb.go b/src/machine/machine_py32_pin_clock_ahb.go new file mode 100644 index 0000000000..dda97e3354 --- /dev/null +++ b/src/machine/machine_py32_pin_clock_ahb.go @@ -0,0 +1,10 @@ +//go:build py32 && py32_gpio_clock_ahb + +package machine + +import "device/py32" + +func (p Pin) enableClock() { + // PY32F410 places IOPAEN at bit 8 of AHBENR. + py32.RCC.AHBENR.SetBits(1 << (p.getPortNumber() + 8)) +} diff --git a/src/machine/machine_py32_pin_clock_ahb1.go b/src/machine/machine_py32_pin_clock_ahb1.go new file mode 100644 index 0000000000..62d0d30ace --- /dev/null +++ b/src/machine/machine_py32_pin_clock_ahb1.go @@ -0,0 +1,10 @@ +//go:build py32 && py32_gpio_clock_ahb1 + +package machine + +import "device/py32" + +func (p Pin) enableClock() { + // PY32E407/F403 use STM32F4-style GPIO clock bits starting at bit 0. + py32.RCC.AHB1ENR.SetBits(1 << p.getPortNumber()) +} diff --git a/src/machine/machine_py32_pin_speed.go b/src/machine/machine_py32_pin_speed.go new file mode 100644 index 0000000000..1cfcbea937 --- /dev/null +++ b/src/machine/machine_py32_pin_speed.go @@ -0,0 +1,9 @@ +//go:build py32 && !py32_gpio_ospdder + +package machine + +import "device/py32" + +func setPinOutputSpeed(port *py32.GPIO_Type, speed uint32, pos uint8) { + port.OSPEEDR.ReplaceBits(speed, gpioOutputSpeedMask, pos) +} diff --git a/src/machine/machine_py32_pin_speed_ospdder.go b/src/machine/machine_py32_pin_speed_ospdder.go new file mode 100644 index 0000000000..ba2c7199c1 --- /dev/null +++ b/src/machine/machine_py32_pin_speed_ospdder.go @@ -0,0 +1,9 @@ +//go:build py32 && py32_gpio_ospdder + +package machine + +import "device/py32" + +func setPinOutputSpeed(port *py32.GPIO_Type, speed uint32, pos uint8) { + port.OSPDDER.ReplaceBits(speed, gpioOutputSpeedMask, pos) +} diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index ea97f1c15a..4136a5d90c 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -1,4 +1,4 @@ -//go:build py32 +//go:build py32 && !py32_uart_type package machine @@ -7,21 +7,6 @@ import ( "runtime/interrupt" ) -// errUARTWriteTimeout is returned by writeByte when the TX register does not -// become empty within the retry budget. -type uartError string - -func (e uartError) Error() string { return string(e) } - -const errUARTWriteTimeout uartError = "UART: write timeout" - -// uartTXRetries is the upper bound on the SR polling loop in writeByte and -// flush. At the PY32F maximum CPU frequency of 48 MHz, an APB peripheral read -// plus loop overhead costs roughly 5 cycles (~104 ns). One byte at 9600 baud -// takes ~1.04 ms, which at that rate corresponds to ~10 000 iterations — the -// worst case for any standard baud rate at the highest supported clock. -const uartTXRetries = 10000 - // UART implements a minimal USART driver for PY32 parts. It works with any of // the on-chip USART peripherals: the peripheral-specific wiring (clock gate and // RX interrupt) is provided by the setup function stored on the instance, which @@ -34,7 +19,7 @@ type UART struct { } // DefaultUART is the first USART (USART1) and backs machine.Serial. -var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer(), setup: setupUSART1} +var DefaultUART = &UART{Bus: defaultUSART(), Buffer: NewRingBuffer(), setup: setupUSART1} func (uart *UART) Configure(config UARTConfig) error { @@ -69,14 +54,12 @@ func (uart *UART) Configure(config UARTConfig) error { // without the var initializer forming an initialization cycle. func setupUSART1(uart *UART) { usart1RX = uart - py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) - uart.irq = interrupt.New(py32.IRQ_USART1, handleUSART1Interrupt) - uart.irq.SetPriority(0xc0) - uart.irq.Enable() + enableUSART1Clock() + configureUSART1Interrupt(uart) } func handleUSART1Interrupt(interrupt.Interrupt) { - usart1RX.Receive(uint8(usart1RX.Bus.DR.Get())) + usart1RX.Receive(uint8(readUSARTData(usart1RX.Bus))) } // usart1RX is the UART whose RX interrupt is serviced by handleUSART1Interrupt. @@ -87,19 +70,19 @@ var usart1RX *UART func (uart *UART) writeByte(c byte) error { retries := uartTXRetries - for retries > 0 && uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { + for retries > 0 && !usartTXReady(uart.Bus) { retries-- } if retries <= 0 { return errUARTWriteTimeout } - uart.Bus.DR.Set(uint32(c)) + writeUSARTData(uart.Bus, uint32(c)) return nil } func (uart *UART) flush() { retries := uartTXRetries - for retries > 0 && uart.Bus.SR.Get()&py32.USART_SR_TC == 0 { + for retries > 0 && !usartTXComplete(uart.Bus) { retries-- } } diff --git a/src/machine/machine_py32_uart_clock.go b/src/machine/machine_py32_uart_clock.go new file mode 100644 index 0000000000..2644d266c6 --- /dev/null +++ b/src/machine/machine_py32_uart_clock.go @@ -0,0 +1,10 @@ +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 + +package machine + +import "device/py32" + +func enableUSART1Clock() { + // USART1EN is bit 14 even in SVDs that omit the field metadata. + py32.RCC.APBENR2.SetBits(1 << 14) +} diff --git a/src/machine/machine_py32_uart_clock_apb2.go b/src/machine/machine_py32_uart_clock_apb2.go new file mode 100644 index 0000000000..e95ab08510 --- /dev/null +++ b/src/machine/machine_py32_uart_clock_apb2.go @@ -0,0 +1,9 @@ +//go:build py32 && !py32_uart_type && py32_uart_clock_apb2 + +package machine + +import "device/py32" + +func enableUSART1Clock() { + py32.RCC.APB2ENR.SetBits(1 << 14) +} diff --git a/src/machine/machine_py32_uart_common.go b/src/machine/machine_py32_uart_common.go new file mode 100644 index 0000000000..3b8a4ceab7 --- /dev/null +++ b/src/machine/machine_py32_uart_common.go @@ -0,0 +1,15 @@ +//go:build py32 + +package machine + +// errUARTWriteTimeout is returned by writeByte when the TX register does not +// become empty within the retry budget. +type uartError string + +func (e uartError) Error() string { return string(e) } + +const errUARTWriteTimeout uartError = "UART: write timeout" + +// uartTXRetries is the upper bound on the transmit status polling loops. At +// 48 MHz, 10,000 peripheral reads cover more than one byte at 9600 baud. +const uartTXRetries = 10000 diff --git a/src/machine/machine_py32_uart_data.go b/src/machine/machine_py32_uart_data.go new file mode 100644 index 0000000000..154f0538ef --- /dev/null +++ b/src/machine/machine_py32_uart_data.go @@ -0,0 +1,21 @@ +//go:build py32 && !py32_uart_type && !py32_usart_split_data + +package machine + +import "device/py32" + +func readUSARTData(bus *py32.USART_Type) uint32 { + return bus.DR.Get() +} + +func writeUSARTData(bus *py32.USART_Type, value uint32) { + bus.DR.Set(value) +} + +func usartTXReady(bus *py32.USART_Type) bool { + return bus.SR.Get()&0x80 != 0 +} + +func usartTXComplete(bus *py32.USART_Type) bool { + return bus.SR.Get()&0x40 != 0 +} diff --git a/src/machine/machine_py32_uart_data_split.go b/src/machine/machine_py32_uart_data_split.go new file mode 100644 index 0000000000..82485ee1df --- /dev/null +++ b/src/machine/machine_py32_uart_data_split.go @@ -0,0 +1,21 @@ +//go:build py32 && py32_usart_split_data + +package machine + +import "device/py32" + +func readUSARTData(bus *py32.USART_Type) uint32 { + return bus.RDR.Get() +} + +func writeUSARTData(bus *py32.USART_Type, value uint32) { + bus.TDR.Set(value) +} + +func usartTXReady(bus *py32.USART_Type) bool { + return bus.SR.Get()&0x80 != 0 +} + +func usartTXComplete(bus *py32.USART_Type) bool { + return bus.SR.Get()&0x40 != 0 +} diff --git a/src/machine/machine_py32_uart_interrupt.go b/src/machine/machine_py32_uart_interrupt.go new file mode 100644 index 0000000000..c543450c31 --- /dev/null +++ b/src/machine/machine_py32_uart_interrupt.go @@ -0,0 +1,14 @@ +//go:build py32 && !py32_uart_type && !py32_uart_no_interrupt + +package machine + +import ( + "device/py32" + "runtime/interrupt" +) + +func configureUSART1Interrupt(uart *UART) { + uart.irq = interrupt.New(py32.IRQ_USART1, handleUSART1Interrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() +} diff --git a/src/machine/machine_py32_uart_no_interrupt.go b/src/machine/machine_py32_uart_no_interrupt.go new file mode 100644 index 0000000000..bcf11bc9bc --- /dev/null +++ b/src/machine/machine_py32_uart_no_interrupt.go @@ -0,0 +1,8 @@ +//go:build py32 && !py32_uart_type && py32_uart_no_interrupt + +package machine + +// The F410 SVD does not provide USART interrupt metadata. Keep transmit and +// configuration support without inventing an IRQ number. +func configureUSART1Interrupt(uart *UART) { +} diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go new file mode 100644 index 0000000000..e288841a48 --- /dev/null +++ b/src/machine/machine_py32_uart_type.go @@ -0,0 +1,57 @@ +//go:build py32 && py32_uart_type + +package machine + +import ( + "device/py32" + "runtime/interrupt" +) + +type UART struct { + Bus *py32.UART_Type + Buffer *RingBuffer + irq interrupt.Interrupt +} + +var DefaultUART = &UART{Bus: py32.UART1, Buffer: NewRingBuffer()} + +func (uart *UART) Configure(config UARTConfig) error { + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + py32.RCC.APBENR1.SetBits(1 << 17) + uart.Bus.CR1.Set(0) + uart.Bus.CR2.Set(1) // RXNEIE + uart.Bus.CR3.Set(0) + uart.Bus.BRR.Set((CPUFrequency() + config.BaudRate/2) / config.BaudRate) + + uart.irq = interrupt.New(py32.IRQ_UART1, handleUART1Interrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() + configureDefaultUARTPins() + return nil +} + +func handleUART1Interrupt(interrupt.Interrupt) { + DefaultUART.Receive(uint8(DefaultUART.Bus.DR.Get())) +} + +func (uart *UART) writeByte(c byte) error { + retries := uartTXRetries + for retries > 0 && uart.Bus.SR.Get()&0x40 == 0 { + retries-- + } + if retries <= 0 { + return errUARTWriteTimeout + } + uart.Bus.DR.Set(uint32(c)) + return nil +} + +func (uart *UART) flush() { + retries := uartTXRetries + for retries > 0 && uart.Bus.SR.Get()&0x40 == 0 { + retries-- + } +} diff --git a/src/machine/machine_py32_uart_usart.go b/src/machine/machine_py32_uart_usart.go new file mode 100644 index 0000000000..099c83e0c5 --- /dev/null +++ b/src/machine/machine_py32_uart_usart.go @@ -0,0 +1,9 @@ +//go:build py32 && !py32_uart_type && !py32_usart_unnumbered + +package machine + +import "device/py32" + +func defaultUSART() *py32.USART_Type { + return py32.USART1 +} diff --git a/src/machine/machine_py32_uart_usart_unnumbered.go b/src/machine/machine_py32_uart_usart_unnumbered.go new file mode 100644 index 0000000000..89191a2bfd --- /dev/null +++ b/src/machine/machine_py32_uart_usart_unnumbered.go @@ -0,0 +1,9 @@ +//go:build py32 && py32_usart_unnumbered + +package machine + +import "device/py32" + +func defaultUSART() *py32.USART_Type { + return py32.USART +} diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 965d0bc020..610e7a4a1e 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -6,21 +6,16 @@ import ( "device/arm" "machine" - "device/py32" - "runtime/volatile" ) var tickCounter volatile.Register64 -// Puya's raw SVDs define HSI_FS but omit its enumerated values. -const rccICSCRHSIFrequency24MHz = 4 - //export Reset_Handler func main() { preinit() - py32.RCC.SetICSCR_HSI_FS(rccICSCRHSIFrequency24MHz) + configureHSI() ConfigureSystemTimer() machine.InitSerial() diff --git a/src/runtime/runtime_py32_hsi.go b/src/runtime/runtime_py32_hsi.go new file mode 100644 index 0000000000..b172977fd6 --- /dev/null +++ b/src/runtime/runtime_py32_hsi.go @@ -0,0 +1,11 @@ +//go:build py32 && !py32_hsi_fs_op && !py32_no_hsi_fs + +package runtime + +import "device/py32" + +// Puya's raw SVDs define HSI_FS but omit its enumerated values. Value 4 selects +// the 24 MHz clock used by the common PY32 runtime. +func configureHSI() { + py32.RCC.SetICSCR_HSI_FS(4) +} diff --git a/src/runtime/runtime_py32_hsi_none.go b/src/runtime/runtime_py32_hsi_none.go new file mode 100644 index 0000000000..c6443cd6b4 --- /dev/null +++ b/src/runtime/runtime_py32_hsi_none.go @@ -0,0 +1,8 @@ +//go:build py32 && py32_no_hsi_fs + +package runtime + +// The M4 SVDs do not expose the M0+ ICSCR.HSI_FS selector. Preserve the reset +// clock configuration instead of writing an unverified register encoding. +func configureHSI() { +} diff --git a/src/runtime/runtime_py32_hsi_op.go b/src/runtime/runtime_py32_hsi_op.go new file mode 100644 index 0000000000..a3ea50be15 --- /dev/null +++ b/src/runtime/runtime_py32_hsi_op.go @@ -0,0 +1,9 @@ +//go:build py32 && py32_hsi_fs_op + +package runtime + +import "device/py32" + +func configureHSI() { + py32.RCC.SetICSCR_HSI_FS_OP(4) +} diff --git a/targets/py32e407xx.json b/targets/py32e407xx.json index 5d071bdb94..b354d5169c 100644 --- a/targets/py32e407xx.json +++ b/targets/py32e407xx.json @@ -3,7 +3,12 @@ "py32-m4" ], "build-tags": [ - "py32e407xx" + "py32e407xx", + "py32_gpio_ospdder", + "py32_gpio_clock_ahb1", + "py32_no_hsi_fs", + "py32_usart_split_data", + "py32_uart_clock_apb2" ], "extra-files": [ "src/device/py32/py32e407xx.s" diff --git a/targets/py32f403xx.json b/targets/py32f403xx.json index d3b24b7c6f..b53c763ef0 100644 --- a/targets/py32f403xx.json +++ b/targets/py32f403xx.json @@ -3,7 +3,10 @@ "py32-m4" ], "build-tags": [ - "py32f403xx" + "py32f403xx", + "py32_gpio_clock_ahb1", + "py32_no_hsi_fs", + "py32_uart_clock_apb2" ], "extra-files": [ "src/device/py32/py32f403xx.s" diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json index 5578e13851..154465b63e 100644 --- a/targets/py32f410xx.json +++ b/targets/py32f410xx.json @@ -3,7 +3,13 @@ "py32-m4" ], "build-tags": [ - "py32f410xx" + "py32f410xx", + "py32_gpio_ospdder", + "py32_gpio_clock_ahb", + "py32_no_hsi_fs", + "py32_usart_unnumbered", + "py32_uart_clock_apb2", + "py32_uart_no_interrupt" ], "extra-files": [ "src/device/py32/py32f410xx.s" diff --git a/targets/py32l090xx.json b/targets/py32l090xx.json index 4855b99d2b..fa6fe329b7 100644 --- a/targets/py32l090xx.json +++ b/targets/py32l090xx.json @@ -3,7 +3,9 @@ "py32" ], "build-tags": [ - "py32l090xx" + "py32l090xx", + "py32_gpio_ospdder", + "py32_hsi_fs_op" ], "extra-files": [ "src/device/py32/py32l090xx.s" diff --git a/targets/py32t020xx.json b/targets/py32t020xx.json index 473ec395f6..7764148fd0 100644 --- a/targets/py32t020xx.json +++ b/targets/py32t020xx.json @@ -3,7 +3,8 @@ "py32" ], "build-tags": [ - "py32t020xx" + "py32t020xx", + "py32_uart_type" ], "extra-files": [ "src/device/py32/py32t020xx.s" diff --git a/targets/py32t090xx.json b/targets/py32t090xx.json index 1c94725f27..5388f54716 100644 --- a/targets/py32t090xx.json +++ b/targets/py32t090xx.json @@ -3,7 +3,9 @@ "py32" ], "build-tags": [ - "py32t090xx" + "py32t090xx", + "py32_gpio_ospdder", + "py32_hsi_fs_op" ], "extra-files": [ "src/device/py32/py32t090xx.s" diff --git a/targets/py32t092xx.json b/targets/py32t092xx.json index 5e6d6adac5..b4b57b99d0 100644 --- a/targets/py32t092xx.json +++ b/targets/py32t092xx.json @@ -3,7 +3,9 @@ "py32" ], "build-tags": [ - "py32t092xx" + "py32t092xx", + "py32_gpio_ospdder", + "py32_hsi_fs_op" ], "extra-files": [ "src/device/py32/py32t092xx.s" diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index 0c70dfcd7a..e699d0b437 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -22,6 +22,19 @@ Cortex-M0+ families inherit `py32`; PY32E407, PY32F403, and PY32F410 families inherit `py32-m4`, which uses TinyGo's standard soft-float Cortex-M4 ABI. Targets whose SVD has no `GPIO.AFRH` register receive the `no_gpio_afrh` build tag. +Puya's SVDs are inconsistent about GPIO `groupName`: some describe identical +ports as `GPIOA_Type`, `GPIOB_Type`, and so on, while others use one +`GPIO_Type`. The `py32-svd` updater validates the register structures and +patches the published SVDs to use the common `GPIO` group. This is a correction +to the vendor metadata, not a target capability, so neither TinyGo's generic +SVD generator nor the target build tags need PY32-specific handling for it. + +Real register-layout differences are selected by generated capability tags. +These cover the `OSPEEDR`/`OSPDDER` GPIO spelling, RCC GPIO and UART clock +registers, `USART` versus `UART` blocks, split USART receive/transmit data +registers, and HSI selector availability. Keep these classifications in the +target generator rather than adding long family expressions to machine files. + Existing PY32 target files are retained for compatibility. In particular, their established aliases and flashing commands are not regenerated. Newly generated targets intentionally omit flashing commands because a compatible programmer @@ -29,10 +42,11 @@ identifier has not been verified for every Puya part. ## Machine support status -All target definitions can be loaded independently of machine-driver support. -A minimal program currently compiles for 68 of the 87 concrete targets. The -remaining targets are E407, F001C, F002C, F032, F403, F410, L090, T020, T090, -and T092 devices whose raw SVD register layouts do not match assumptions in the -existing generic PY32 GPIO, RCC, or UART implementations. Their definitions are -included deliberately so machine support can be added without revisiting target -and linker metadata. \ No newline at end of file +A minimal program compiles for all 87 concrete targets. GPIO, RCC, runtime +clock setup, and the default serial block are selected according to each SVD's +register layout. This is compile-time coverage, not hardware validation for +every device. In particular, PY32F410 SVD interrupt metadata stops before the +serial interrupts, so its default USART is configured without receive +interrupts rather than assigning an unverified IRQ number. The M4 SVDs also do +not expose the M0+ `ICSCR.HSI_FS` selector, so the runtime preserves their reset +clock configuration. \ No newline at end of file diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 27172fd0da..5d6b4dc72e 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -49,6 +49,51 @@ var noGPIOAFRH = map[string]bool{ "py32m010xx": true, } +var gpioOSPDDER = familySet("py32e407xx", "py32f410xx", "py32l090xx", "py32t090xx", "py32t092xx") +var gpioClockAHB1 = familySet("py32e407xx", "py32f403xx") +var gpioClockAHB = familySet("py32f410xx") +var hsiFSOP = familySet("py32l090xx", "py32t090xx", "py32t092xx") +var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") +var uartType = familySet("py32t020xx") +var usartSplitData = familySet("py32e407xx") +var usartUnnumbered = familySet("py32f410xx") +var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") +var uartNoInterrupt = familySet("py32f410xx") + +func familySet(names ...string) map[string]bool { + set := make(map[string]bool, len(names)) + for _, name := range names { + set[name] = true + } + return set +} + +func familyBuildTags(family string) []string { + tags := []string{family} + features := []struct { + name string + set map[string]bool + }{ + {"no_gpio_afrh", noGPIOAFRH}, + {"py32_gpio_ospdder", gpioOSPDDER}, + {"py32_gpio_clock_ahb1", gpioClockAHB1}, + {"py32_gpio_clock_ahb", gpioClockAHB}, + {"py32_hsi_fs_op", hsiFSOP}, + {"py32_no_hsi_fs", noHSIFS}, + {"py32_uart_type", uartType}, + {"py32_usart_split_data", usartSplitData}, + {"py32_usart_unnumbered", usartUnnumbered}, + {"py32_uart_clock_apb2", uartClockAPB2}, + {"py32_uart_no_interrupt", uartNoInterrupt}, + } + for _, feature := range features { + if feature.set[family] { + tags = append(tags, feature.name) + } + } + return tags +} + var legacyTargets = map[string]bool{ // Keep pre-existing definitions, including established aliases and flashing // commands. New definitions intentionally contain no flashing command. @@ -158,13 +203,9 @@ func generate(out string, devices []device) error { if families[family] == "m4" { base = "py32-m4" } - tags := []string{family} - if noGPIOAFRH[family] { - tags = append(tags, "no_gpio_afrh") - } spec := target{ Inherits: []string{base}, - BuildTags: tags, + BuildTags: familyBuildTags(family), ExtraFiles: []string{"src/device/py32/" + family + ".s"}, } if err := writeJSON(filepath.Join(out, family+".json"), spec); err != nil { diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index 4789154faf..c034cab088 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "strings" "testing" ) @@ -58,6 +59,9 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32e407xc.json"), "py32e407xx", "targets/py32e407xc.ld") checkTarget(t, filepath.Join(out, "py32f001xx.json"), "py32", "") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "") + checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb1", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") + checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") + checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) if err != nil { @@ -72,6 +76,21 @@ func TestGenerate(t *testing.T) { } } +func checkBuildTags(t *testing.T, path string, want ...string) { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var spec target + if err := json.Unmarshal(data, &spec); err != nil { + t.Fatal(err) + } + if got := strings.Join(spec.BuildTags, ","); got != strings.Join(want, ",") { + t.Errorf("%s build tags are %q, want %q", path, got, strings.Join(want, ",")) + } +} + func checkTarget(t *testing.T, path, inherited, linker string) { t.Helper() data, err := os.ReadFile(path) From 116db61647967c6687c7f2058a6c0fe35addf56e Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 6 Aug 2026 06:36:42 +0200 Subject: [PATCH 38/62] machine/py32: use generated register definitions --- lib/py32-svd | 2 +- src/machine/machine_py32_pin.go | 17 +++++++-------- src/machine/machine_py32_pin_afrh.go | 6 ++++-- src/machine/machine_py32_pin_clock.go | 4 ++-- src/machine/machine_py32_pin_clock_ahb.go | 3 +-- src/machine/machine_py32_pin_clock_ahb1.go | 10 --------- src/machine/machine_py32_pin_clock_ahb2.go | 9 ++++++++ src/machine/machine_py32_pin_no_afrh.go | 4 +++- src/machine/machine_py32_pin_speed.go | 5 +++++ src/machine/machine_py32_pin_speed_ospdder.go | 5 +++++ src/machine/machine_py32_uart_clock.go | 5 ++--- src/machine/machine_py32_uart_clock_apb2.go | 2 +- .../machine_py32_uart_clock_literal.go | 11 ++++++++++ src/machine/machine_py32_uart_data.go | 6 +++--- src/machine/machine_py32_uart_data_split.go | 4 ++-- src/machine/machine_py32_uart_data_txe_txf.go | 21 +++++++++++++++++++ src/machine/machine_py32_uart_type.go | 8 +++---- src/runtime/runtime_py32_hsi.go | 6 ++---- src/runtime/runtime_py32_hsi_literal3.go | 12 +++++++++++ src/runtime/runtime_py32_hsi_literal4.go | 12 +++++++++++ src/runtime/runtime_py32_hsi_op.go | 2 ++ targets/py32e407xx.json | 2 +- targets/py32f001cxx.json | 4 +++- targets/py32f001xx.json | 4 +++- targets/py32f002cxx.json | 3 ++- targets/py32f032xx.json | 3 ++- targets/py32f403xx.json | 2 +- targets/py32f410xx.json | 1 + tools/gen-py32-targets/main.go | 12 +++++++++-- tools/gen-py32-targets/main_test.go | 7 +++++-- 30 files changed, 138 insertions(+), 54 deletions(-) delete mode 100644 src/machine/machine_py32_pin_clock_ahb1.go create mode 100644 src/machine/machine_py32_pin_clock_ahb2.go create mode 100644 src/machine/machine_py32_uart_clock_literal.go create mode 100644 src/machine/machine_py32_uart_data_txe_txf.go create mode 100644 src/runtime/runtime_py32_hsi_literal3.go create mode 100644 src/runtime/runtime_py32_hsi_literal4.go diff --git a/lib/py32-svd b/lib/py32-svd index 2de730eb83..982b09364d 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit 2de730eb8306f06f8d20350769dbc3986deeb3e5 +Subproject commit 982b09364d84bf829b172d3e43b14f81b325ad7d diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 3f4039c7d8..e086595dd4 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -145,27 +145,26 @@ const ( ) const PinInput PinMode = PinInputFloating -// Puya's raw SVDs define these fields and masks but do not provide their -// enumerated values. These encodings are shared by the supported PY32 parts. +// These unshifted encodings are shared by the supported PY32 parts. Register +// masks come from the generated device definitions. const ( gpioModeInput = 0 gpioModeOutput = 1 gpioModeAlternate = 2 gpioModeAnalog = 3 - gpioModeMask = 0x3 gpioPullFloating = 0 gpioPullUp = 1 gpioPullDown = 2 - gpioPullMask = 0x3 + gpioPullMask = py32.GPIO_PUPDR_PUPD0_Msk gpioOutputSpeedLow = 0 gpioOutputSpeedMedium = 1 gpioOutputSpeedHigh = 2 gpioOutputSpeedVeryHigh = 3 - gpioOutputSpeedMask = 0x3 gpioOutputTypePushPull = 0 + gpioOutputTypeMask = py32.GPIO_OTYPER_OT0_Msk ) func (p Pin) getPortNumber() uint8 { @@ -184,15 +183,15 @@ func (p Pin) getPort() (*py32.GPIO_Type, uint8) { func (p Pin) Set(high bool) { port, pin := p.getPort() if high { - port.BSRR.Set(1 << pin) + port.BSRR.Set(py32.GPIO_BSRR_BS0 << pin) } else { - port.BSRR.Set(1 << (pin + 16)) + port.BSRR.Set(py32.GPIO_BSRR_BR0 << pin) } } func (p Pin) Get() bool { port, pin := p.getPort() - val := port.IDR.Get() & (1 << pin) + val := port.IDR.Get() & (py32.GPIO_IDR_ID0 << pin) return val > 0 } @@ -214,7 +213,7 @@ func (p Pin) Configure(config PinConfig) { port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) case PinOutput: port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos) - port.OTYPER.ReplaceBits(gpioOutputTypePushPull, 0x1, pos>>1) + port.OTYPER.ReplaceBits(gpioOutputTypePushPull, gpioOutputTypeMask, pos>>1) setPinOutputSpeed(port, gpioOutputSpeedHigh, pos) case PinInputAnalog: port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 02ec04cda3..9a4fd65f97 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -2,6 +2,8 @@ package machine +import "device/py32" + // SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. // // Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a @@ -17,8 +19,8 @@ package machine func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() if pin >= 8 { - port.AFRH.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + port.AFRH.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4) } else { - port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + port.AFRL.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4) } } diff --git a/src/machine/machine_py32_pin_clock.go b/src/machine/machine_py32_pin_clock.go index 167b1ac8e4..e5c575f60f 100644 --- a/src/machine/machine_py32_pin_clock.go +++ b/src/machine/machine_py32_pin_clock.go @@ -1,9 +1,9 @@ -//go:build py32 && !py32_gpio_clock_ahb1 && !py32_gpio_clock_ahb +//go:build py32 && !py32_gpio_clock_ahb2 && !py32_gpio_clock_ahb package machine import "device/py32" func (p Pin) enableClock() { - py32.RCC.IOPENR.SetBits(1 << p.getPortNumber()) + py32.RCC.IOPENR.SetBits(py32.RCC_IOPENR_GPIOAEN << p.getPortNumber()) } diff --git a/src/machine/machine_py32_pin_clock_ahb.go b/src/machine/machine_py32_pin_clock_ahb.go index dda97e3354..6ac7e62d8e 100644 --- a/src/machine/machine_py32_pin_clock_ahb.go +++ b/src/machine/machine_py32_pin_clock_ahb.go @@ -5,6 +5,5 @@ package machine import "device/py32" func (p Pin) enableClock() { - // PY32F410 places IOPAEN at bit 8 of AHBENR. - py32.RCC.AHBENR.SetBits(1 << (p.getPortNumber() + 8)) + py32.RCC.AHBENR.SetBits(py32.RCC_AHBENR_IOPAEN << p.getPortNumber()) } diff --git a/src/machine/machine_py32_pin_clock_ahb1.go b/src/machine/machine_py32_pin_clock_ahb1.go deleted file mode 100644 index 62d0d30ace..0000000000 --- a/src/machine/machine_py32_pin_clock_ahb1.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build py32 && py32_gpio_clock_ahb1 - -package machine - -import "device/py32" - -func (p Pin) enableClock() { - // PY32E407/F403 use STM32F4-style GPIO clock bits starting at bit 0. - py32.RCC.AHB1ENR.SetBits(1 << p.getPortNumber()) -} diff --git a/src/machine/machine_py32_pin_clock_ahb2.go b/src/machine/machine_py32_pin_clock_ahb2.go new file mode 100644 index 0000000000..3daf2728c6 --- /dev/null +++ b/src/machine/machine_py32_pin_clock_ahb2.go @@ -0,0 +1,9 @@ +//go:build py32 && py32_gpio_clock_ahb2 + +package machine + +import "device/py32" + +func (p Pin) enableClock() { + py32.RCC.AHB2ENR.SetBits(py32.RCC_AHB2ENR_IOPAEN << p.getPortNumber()) +} diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index 32c471de16..8e47e33fdb 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -2,6 +2,8 @@ package machine +import "device/py32" + // SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. // // Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a @@ -16,5 +18,5 @@ package machine // Pin.Configure before the alternate function takes effect. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() - port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + port.AFRL.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4) } diff --git a/src/machine/machine_py32_pin_speed.go b/src/machine/machine_py32_pin_speed.go index 1cfcbea937..45addbb766 100644 --- a/src/machine/machine_py32_pin_speed.go +++ b/src/machine/machine_py32_pin_speed.go @@ -4,6 +4,11 @@ package machine import "device/py32" +const ( + gpioModeMask = py32.GPIO_MODER_MODE0_Msk + gpioOutputSpeedMask = py32.GPIO_OSPEEDR_OSPEED0_Msk +) + func setPinOutputSpeed(port *py32.GPIO_Type, speed uint32, pos uint8) { port.OSPEEDR.ReplaceBits(speed, gpioOutputSpeedMask, pos) } diff --git a/src/machine/machine_py32_pin_speed_ospdder.go b/src/machine/machine_py32_pin_speed_ospdder.go index ba2c7199c1..99409ed2ec 100644 --- a/src/machine/machine_py32_pin_speed_ospdder.go +++ b/src/machine/machine_py32_pin_speed_ospdder.go @@ -4,6 +4,11 @@ package machine import "device/py32" +const ( + gpioModeMask = py32.GPIO_MODER_MODER0_Msk + gpioOutputSpeedMask = py32.GPIO_OSPDDER_OSPEED0_Msk +) + func setPinOutputSpeed(port *py32.GPIO_Type, speed uint32, pos uint8) { port.OSPDDER.ReplaceBits(speed, gpioOutputSpeedMask, pos) } diff --git a/src/machine/machine_py32_uart_clock.go b/src/machine/machine_py32_uart_clock.go index 2644d266c6..3f066a2bd7 100644 --- a/src/machine/machine_py32_uart_clock.go +++ b/src/machine/machine_py32_uart_clock.go @@ -1,10 +1,9 @@ -//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && !py32_usart1_clock_literal package machine import "device/py32" func enableUSART1Clock() { - // USART1EN is bit 14 even in SVDs that omit the field metadata. - py32.RCC.APBENR2.SetBits(1 << 14) + py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) } diff --git a/src/machine/machine_py32_uart_clock_apb2.go b/src/machine/machine_py32_uart_clock_apb2.go index e95ab08510..4eeb94429a 100644 --- a/src/machine/machine_py32_uart_clock_apb2.go +++ b/src/machine/machine_py32_uart_clock_apb2.go @@ -5,5 +5,5 @@ package machine import "device/py32" func enableUSART1Clock() { - py32.RCC.APB2ENR.SetBits(1 << 14) + py32.RCC.APB2ENR.SetBits(py32.RCC_APB2ENR_USART1EN) } diff --git a/src/machine/machine_py32_uart_clock_literal.go b/src/machine/machine_py32_uart_clock_literal.go new file mode 100644 index 0000000000..d4352f7510 --- /dev/null +++ b/src/machine/machine_py32_uart_clock_literal.go @@ -0,0 +1,11 @@ +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && py32_usart1_clock_literal + +package machine + +import "device/py32" + +func enableUSART1Clock() { + // The F001 pack omits its referenced device header, and its SVD omits the + // APBENR2 USART1EN field. The vendor system layout places it at bit 14. + py32.RCC.APBENR2.SetBits(1 << 14) +} diff --git a/src/machine/machine_py32_uart_data.go b/src/machine/machine_py32_uart_data.go index 154f0538ef..bc4b89325b 100644 --- a/src/machine/machine_py32_uart_data.go +++ b/src/machine/machine_py32_uart_data.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_uart_type && !py32_usart_split_data +//go:build py32 && !py32_uart_type && !py32_usart_split_data && !py32_usart_txe_txf package machine @@ -13,9 +13,9 @@ func writeUSARTData(bus *py32.USART_Type, value uint32) { } func usartTXReady(bus *py32.USART_Type) bool { - return bus.SR.Get()&0x80 != 0 + return bus.SR.Get()&py32.USART_SR_TXE != 0 } func usartTXComplete(bus *py32.USART_Type) bool { - return bus.SR.Get()&0x40 != 0 + return bus.SR.Get()&py32.USART_SR_TC != 0 } diff --git a/src/machine/machine_py32_uart_data_split.go b/src/machine/machine_py32_uart_data_split.go index 82485ee1df..11017dabba 100644 --- a/src/machine/machine_py32_uart_data_split.go +++ b/src/machine/machine_py32_uart_data_split.go @@ -13,9 +13,9 @@ func writeUSARTData(bus *py32.USART_Type, value uint32) { } func usartTXReady(bus *py32.USART_Type) bool { - return bus.SR.Get()&0x80 != 0 + return bus.SR.Get()&py32.USART_SR_TXE_TXFNF != 0 } func usartTXComplete(bus *py32.USART_Type) bool { - return bus.SR.Get()&0x40 != 0 + return bus.SR.Get()&py32.USART_SR_TC != 0 } diff --git a/src/machine/machine_py32_uart_data_txe_txf.go b/src/machine/machine_py32_uart_data_txe_txf.go new file mode 100644 index 0000000000..8a64150dae --- /dev/null +++ b/src/machine/machine_py32_uart_data_txe_txf.go @@ -0,0 +1,21 @@ +//go:build py32 && !py32_uart_type && !py32_usart_split_data && py32_usart_txe_txf + +package machine + +import "device/py32" + +func readUSARTData(bus *py32.USART_Type) uint32 { + return bus.DR.Get() +} + +func writeUSARTData(bus *py32.USART_Type, value uint32) { + bus.DR.Set(value) +} + +func usartTXReady(bus *py32.USART_Type) bool { + return bus.SR.Get()&py32.USART_SR_TXE_TXFNF != 0 +} + +func usartTXComplete(bus *py32.USART_Type) bool { + return bus.SR.Get()&py32.USART_SR_TC != 0 +} diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go index e288841a48..f58ba3430e 100644 --- a/src/machine/machine_py32_uart_type.go +++ b/src/machine/machine_py32_uart_type.go @@ -20,9 +20,9 @@ func (uart *UART) Configure(config UARTConfig) error { config.BaudRate = 115200 } - py32.RCC.APBENR1.SetBits(1 << 17) + py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_UART1EN) uart.Bus.CR1.Set(0) - uart.Bus.CR2.Set(1) // RXNEIE + uart.Bus.CR2.Set(py32.UART_CR2_RXNEIE) uart.Bus.CR3.Set(0) uart.Bus.BRR.Set((CPUFrequency() + config.BaudRate/2) / config.BaudRate) @@ -39,7 +39,7 @@ func handleUART1Interrupt(interrupt.Interrupt) { func (uart *UART) writeByte(c byte) error { retries := uartTXRetries - for retries > 0 && uart.Bus.SR.Get()&0x40 == 0 { + for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 { retries-- } if retries <= 0 { @@ -51,7 +51,7 @@ func (uart *UART) writeByte(c byte) error { func (uart *UART) flush() { retries := uartTXRetries - for retries > 0 && uart.Bus.SR.Get()&0x40 == 0 { + for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 { retries-- } } diff --git a/src/runtime/runtime_py32_hsi.go b/src/runtime/runtime_py32_hsi.go index b172977fd6..48eea04293 100644 --- a/src/runtime/runtime_py32_hsi.go +++ b/src/runtime/runtime_py32_hsi.go @@ -1,11 +1,9 @@ -//go:build py32 && !py32_hsi_fs_op && !py32_no_hsi_fs +//go:build py32 && !py32_hsi_fs_op && !py32_hsi_fs_literal3 && !py32_hsi_fs_literal4 && !py32_no_hsi_fs package runtime import "device/py32" -// Puya's raw SVDs define HSI_FS but omit its enumerated values. Value 4 selects -// the 24 MHz clock used by the common PY32 runtime. func configureHSI() { - py32.RCC.SetICSCR_HSI_FS(4) + py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_2) } diff --git a/src/runtime/runtime_py32_hsi_literal3.go b/src/runtime/runtime_py32_hsi_literal3.go new file mode 100644 index 0000000000..0d574e8f0e --- /dev/null +++ b/src/runtime/runtime_py32_hsi_literal3.go @@ -0,0 +1,12 @@ +//go:build py32 && py32_hsi_fs_literal3 + +package runtime + +import "device/py32" + +// The F032 header names this field HSI_FS_CR while its SVD names it HSI_FS, so +// no matching header-derived value constants are generated. Puya's official +// system source maps encoding 3 to 24 MHz. +func configureHSI() { + py32.RCC.SetICSCR_HSI_FS(3) +} diff --git a/src/runtime/runtime_py32_hsi_literal4.go b/src/runtime/runtime_py32_hsi_literal4.go new file mode 100644 index 0000000000..0b7c9b8390 --- /dev/null +++ b/src/runtime/runtime_py32_hsi_literal4.go @@ -0,0 +1,12 @@ +//go:build py32 && py32_hsi_fs_literal4 + +package runtime + +import "device/py32" + +// F001 lacks its referenced device header. F002C's header shifts its HSI_FS +// bits by the unrelated LSI_TRIM position. In both cases Puya's official system +// sources map encoding 4 to the runtime's 24 MHz clock. +func configureHSI() { + py32.RCC.SetICSCR_HSI_FS(4) +} diff --git a/src/runtime/runtime_py32_hsi_op.go b/src/runtime/runtime_py32_hsi_op.go index a3ea50be15..3b153be156 100644 --- a/src/runtime/runtime_py32_hsi_op.go +++ b/src/runtime/runtime_py32_hsi_op.go @@ -4,6 +4,8 @@ package runtime import "device/py32" +// The official L090/T09x headers provide HSI_FS_OP position and mask helpers, +// but no value definitions. Encoding 4 selects the runtime's 24 MHz clock. func configureHSI() { py32.RCC.SetICSCR_HSI_FS_OP(4) } diff --git a/targets/py32e407xx.json b/targets/py32e407xx.json index b354d5169c..dabb31491b 100644 --- a/targets/py32e407xx.json +++ b/targets/py32e407xx.json @@ -5,7 +5,7 @@ "build-tags": [ "py32e407xx", "py32_gpio_ospdder", - "py32_gpio_clock_ahb1", + "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2" diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json index 4d426bc2c0..f73e021a97 100644 --- a/targets/py32f001cxx.json +++ b/targets/py32f001cxx.json @@ -4,7 +4,9 @@ ], "build-tags": [ "py32f001cxx", - "no_gpio_afrh" + "no_gpio_afrh", + "py32_hsi_fs_literal4", + "py32_usart1_clock_literal" ], "extra-files": [ "src/device/py32/py32f001cxx.s" diff --git a/targets/py32f001xx.json b/targets/py32f001xx.json index 58248f3e1b..9fedf12b9a 100644 --- a/targets/py32f001xx.json +++ b/targets/py32f001xx.json @@ -3,7 +3,9 @@ "py32" ], "build-tags": [ - "py32f001xx" + "py32f001xx", + "py32_hsi_fs_literal4", + "py32_usart1_clock_literal" ], "extra-files": [ "src/device/py32/py32f001xx.s" diff --git a/targets/py32f002cxx.json b/targets/py32f002cxx.json index 84fa15b05d..fb83d0afee 100644 --- a/targets/py32f002cxx.json +++ b/targets/py32f002cxx.json @@ -4,7 +4,8 @@ ], "build-tags": [ "py32f002cxx", - "no_gpio_afrh" + "no_gpio_afrh", + "py32_hsi_fs_literal4" ], "extra-files": [ "src/device/py32/py32f002cxx.s" diff --git a/targets/py32f032xx.json b/targets/py32f032xx.json index be4cc0c5da..4acca46023 100644 --- a/targets/py32f032xx.json +++ b/targets/py32f032xx.json @@ -3,7 +3,8 @@ "py32" ], "build-tags": [ - "py32f032xx" + "py32f032xx", + "py32_hsi_fs_literal3" ], "extra-files": [ "src/device/py32/py32f032xx.s" diff --git a/targets/py32f403xx.json b/targets/py32f403xx.json index b53c763ef0..1afdd3eaf6 100644 --- a/targets/py32f403xx.json +++ b/targets/py32f403xx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f403xx", - "py32_gpio_clock_ahb1", + "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_uart_clock_apb2" ], diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json index 154465b63e..6e7140562e 100644 --- a/targets/py32f410xx.json +++ b/targets/py32f410xx.json @@ -8,6 +8,7 @@ "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", + "py32_usart_txe_txf", "py32_uart_clock_apb2", "py32_uart_no_interrupt" ], diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 5d6b4dc72e..173aaf6ae6 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -50,13 +50,17 @@ var noGPIOAFRH = map[string]bool{ } var gpioOSPDDER = familySet("py32e407xx", "py32f410xx", "py32l090xx", "py32t090xx", "py32t092xx") -var gpioClockAHB1 = familySet("py32e407xx", "py32f403xx") +var gpioClockAHB2 = familySet("py32e407xx", "py32f403xx") var gpioClockAHB = familySet("py32f410xx") var hsiFSOP = familySet("py32l090xx", "py32t090xx", "py32t092xx") +var hsiFSLiteral3 = familySet("py32f032xx") +var hsiFSLiteral4 = familySet("py32f001cxx", "py32f001xx", "py32f002cxx") var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") var usartUnnumbered = familySet("py32f410xx") +var usartTXETXF = familySet("py32f410xx") +var usart1ClockLiteral = familySet("py32f001cxx", "py32f001xx") var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartNoInterrupt = familySet("py32f410xx") @@ -76,13 +80,17 @@ func familyBuildTags(family string) []string { }{ {"no_gpio_afrh", noGPIOAFRH}, {"py32_gpio_ospdder", gpioOSPDDER}, - {"py32_gpio_clock_ahb1", gpioClockAHB1}, + {"py32_gpio_clock_ahb2", gpioClockAHB2}, {"py32_gpio_clock_ahb", gpioClockAHB}, {"py32_hsi_fs_op", hsiFSOP}, + {"py32_hsi_fs_literal3", hsiFSLiteral3}, + {"py32_hsi_fs_literal4", hsiFSLiteral4}, {"py32_no_hsi_fs", noHSIFS}, {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, {"py32_usart_unnumbered", usartUnnumbered}, + {"py32_usart_txe_txf", usartTXETXF}, + {"py32_usart1_clock_literal", usart1ClockLiteral}, {"py32_uart_clock_apb2", uartClockAPB2}, {"py32_uart_no_interrupt", uartNoInterrupt}, } diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index c034cab088..f3b6a9ad8c 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -59,8 +59,11 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32e407xc.json"), "py32e407xx", "targets/py32e407xc.ld") checkTarget(t, filepath.Join(out, "py32f001xx.json"), "py32", "") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "") - checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb1", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") - checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") + checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") + checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") + checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "no_gpio_afrh", "py32_hsi_fs_literal4") + checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") + checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_usart_txe_txf", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) From f622bcc2ebb0d98ea6fc86277176ccd5110ad798 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:36:48 +0200 Subject: [PATCH 39/62] machine/py32: fix alternate-function documentation --- src/machine/machine_py32_pin_afrh.go | 8 +++----- src/machine/machine_py32_pin_no_afrh.go | 8 +++----- src/machine/machine_py32_uart_no_default_pins.go | 3 +-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 9a4fd65f97..9c0fdd5e1a 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -11,11 +11,9 @@ import "device/py32" // in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for // pins 8–15, with each selector at bit offset (pin%8)*4 within its register. // -// AF0 is the system function (typically GPIO / SWDIO / SWCLK on JTAG pins). -// AF1–AF7 map peripherals such as USART, SPI, I2C, TIM, and MCO depending on -// the specific pin and PY32F variant; consult the alternate-function table in -// the device datasheet. The pin must also be configured as PinAlternate via -// Pin.Configure before the alternate function takes effect. +// Alternate-function mappings vary by pin and PY32 variant; consult the +// device datasheet for the AF0-AF15 mapping. The pin must also be configured +// as PinAlternate via Pin.Configure before the alternate function takes effect. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() if pin >= 8 { diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index 8e47e33fdb..6a3368fe8c 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -11,11 +11,9 @@ import "device/py32" // in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for // pins 8–15, with each selector at bit offset (pin%8)*4 within its register. // -// AF0 is the system function (typically GPIO / SWDIO / SWCLK on JTAG pins). -// AF1–AF7 map peripherals such as USART, SPI, I2C, TIM, and MCO depending on -// the specific pin and PY32F variant; consult the alternate-function table in -// the device datasheet. The pin must also be configured as PinAlternate via -// Pin.Configure before the alternate function takes effect. +// Alternate-function mappings vary by pin and PY32 variant; consult the +// device datasheet for the AF0-AF15 mapping. The pin must also be configured +// as PinAlternate via Pin.Configure before the alternate function takes effect. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() port.AFRL.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4) diff --git a/src/machine/machine_py32_uart_no_default_pins.go b/src/machine/machine_py32_uart_no_default_pins.go index 70259c145a..d88ff9b108 100644 --- a/src/machine/machine_py32_uart_no_default_pins.go +++ b/src/machine/machine_py32_uart_no_default_pins.go @@ -3,6 +3,5 @@ package machine func configureDefaultUARTPins() { - // There are no default UART pins for this board. Configure them in - // application main() using ConfigureUARTPin(). + // There are no default UART pins for this target. } From ed97c2b79d0a563f385a94ab159a6764daeabc59 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:42:13 +0200 Subject: [PATCH 40/62] machine/py32: report the configured CPU frequency --- src/machine/machine_py32_clock.go | 8 +------- src/machine/machine_py32_clock_24mhz.go | 5 +++++ src/machine/machine_py32_clock_8mhz.go | 5 +++++ src/runtime/runtime_py32_hsi_none.go | 4 ++-- tools/gen-py32-targets/README.md | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 src/machine/machine_py32_clock_24mhz.go create mode 100644 src/machine/machine_py32_clock_8mhz.go diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index 0414a55df3..74b84c5ee7 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,12 +2,6 @@ package machine -// This variable must be updated after any change to the system clock from user code. -// Don't forget to re-initialize peripherals that depend on the system clock, such as: -// - runtime.ConfigureSystemTimer() for the system timer -// - machine.DefaultUART.Configure() if UART is in use -var CPUFrequencyHz uint32 = 24_000_000 - func CPUFrequency() uint32 { - return CPUFrequencyHz + return cpuFrequencyHz } diff --git a/src/machine/machine_py32_clock_24mhz.go b/src/machine/machine_py32_clock_24mhz.go new file mode 100644 index 0000000000..08f2a69c58 --- /dev/null +++ b/src/machine/machine_py32_clock_24mhz.go @@ -0,0 +1,5 @@ +//go:build py32 && !py32_no_hsi_fs + +package machine + +const cpuFrequencyHz = 24_000_000 diff --git a/src/machine/machine_py32_clock_8mhz.go b/src/machine/machine_py32_clock_8mhz.go new file mode 100644 index 0000000000..88e9b8ef57 --- /dev/null +++ b/src/machine/machine_py32_clock_8mhz.go @@ -0,0 +1,5 @@ +//go:build py32 && py32_no_hsi_fs + +package machine + +const cpuFrequencyHz = 8_000_000 diff --git a/src/runtime/runtime_py32_hsi_none.go b/src/runtime/runtime_py32_hsi_none.go index c6443cd6b4..c6e9fd1c9d 100644 --- a/src/runtime/runtime_py32_hsi_none.go +++ b/src/runtime/runtime_py32_hsi_none.go @@ -2,7 +2,7 @@ package runtime -// The M4 SVDs do not expose the M0+ ICSCR.HSI_FS selector. Preserve the reset -// clock configuration instead of writing an unverified register encoding. +// The M4 SVDs do not expose the M0+ ICSCR.HSI_FS selector. Preserve their +// vendor-defined 8 MHz reset clock instead of writing an unverified encoding. func configureHSI() { } diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index e699d0b437..1adacd6bf4 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -49,4 +49,4 @@ every device. In particular, PY32F410 SVD interrupt metadata stops before the serial interrupts, so its default USART is configured without receive interrupts rather than assigning an unverified IRQ number. The M4 SVDs also do not expose the M0+ `ICSCR.HSI_FS` selector, so the runtime preserves their reset -clock configuration. \ No newline at end of file +clock configuration and reports the vendor-defined 8 MHz reset frequency. \ No newline at end of file From 882e08cc94be13dbb65b5c3a81586d6115b256f1 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:43:15 +0200 Subject: [PATCH 41/62] machine/py32: use unsafe.Add for GPIO ports --- src/machine/machine_py32_pin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index e086595dd4..284f2963ff 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -177,7 +177,7 @@ func (p Pin) getPinNumber() uint8 { func (p Pin) getPort() (*py32.GPIO_Type, uint8) { offset := uintptr(p.getPortNumber()) * (uintptr(unsafe.Pointer(py32.GPIOB)) - uintptr(unsafe.Pointer(py32.GPIOA))) - return (*py32.GPIO_Type)(unsafe.Pointer(uintptr(unsafe.Pointer(py32.GPIOA)) + offset)), p.getPinNumber() + return (*py32.GPIO_Type)(unsafe.Add(unsafe.Pointer(py32.GPIOA), offset)), p.getPinNumber() } func (p Pin) Set(high bool) { From 78166de3a4c83300d06d04318faa526ae74ffbd1 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:45:49 +0200 Subject: [PATCH 42/62] machine/py32: bound and yield UART polling --- src/machine/machine_py32_uart.go | 16 ++++++++++------ src/machine/machine_py32_uart_common.go | 18 +++++++++++++++--- src/machine/machine_py32_uart_type.go | 14 +++++++++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index 4136a5d90c..4fade009b3 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -12,10 +12,11 @@ import ( // RX interrupt) is provided by the setup function stored on the instance, which // is set when the instance is created (see setupUSART1 / setupUSART2). type UART struct { - Bus *py32.USART_Type - Buffer *RingBuffer - irq interrupt.Interrupt - setup func(*UART) + Bus *py32.USART_Type + Buffer *RingBuffer + irq interrupt.Interrupt + setup func(*UART) + txRetries uint32 } // DefaultUART is the first USART (USART1) and backs machine.Serial. @@ -26,6 +27,7 @@ func (uart *UART) Configure(config UARTConfig) error { if config.BaudRate == 0 { config.BaudRate = 115200 } + uart.txRetries = uartTXRetryBudget(config.BaudRate) // Enable the peripheral clock and hook its RX interrupt. uart.setup(uart) @@ -69,8 +71,9 @@ func handleUSART1Interrupt(interrupt.Interrupt) { var usart1RX *UART func (uart *UART) writeByte(c byte) error { - retries := uartTXRetries + retries := uart.txRetries for retries > 0 && !usartTXReady(uart.Bus) { + uartYield() retries-- } if retries <= 0 { @@ -81,8 +84,9 @@ func (uart *UART) writeByte(c byte) error { } func (uart *UART) flush() { - retries := uartTXRetries + retries := uart.txRetries for retries > 0 && !usartTXComplete(uart.Bus) { + uartYield() retries-- } } diff --git a/src/machine/machine_py32_uart_common.go b/src/machine/machine_py32_uart_common.go index 3b8a4ceab7..5f6a37caa7 100644 --- a/src/machine/machine_py32_uart_common.go +++ b/src/machine/machine_py32_uart_common.go @@ -2,6 +2,8 @@ package machine +import "runtime/interrupt" + // errUARTWriteTimeout is returned by writeByte when the TX register does not // become empty within the retry budget. type uartError string @@ -10,6 +12,16 @@ func (e uartError) Error() string { return string(e) } const errUARTWriteTimeout uartError = "UART: write timeout" -// uartTXRetries is the upper bound on the transmit status polling loops. At -// 48 MHz, 10,000 peripheral reads cover more than one byte at 9600 baud. -const uartTXRetries = 10000 +func uartTXRetryBudget(baudRate uint32) uint32 { + retries := CPUFrequency() / baudRate * 10 + if retries < 10 { + return 10 + } + return retries +} + +func uartYield() { + if !interrupt.In() { + gosched() + } +} diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go index f58ba3430e..9b69cf5eae 100644 --- a/src/machine/machine_py32_uart_type.go +++ b/src/machine/machine_py32_uart_type.go @@ -8,9 +8,10 @@ import ( ) type UART struct { - Bus *py32.UART_Type - Buffer *RingBuffer - irq interrupt.Interrupt + Bus *py32.UART_Type + Buffer *RingBuffer + irq interrupt.Interrupt + txRetries uint32 } var DefaultUART = &UART{Bus: py32.UART1, Buffer: NewRingBuffer()} @@ -19,6 +20,7 @@ func (uart *UART) Configure(config UARTConfig) error { if config.BaudRate == 0 { config.BaudRate = 115200 } + uart.txRetries = uartTXRetryBudget(config.BaudRate) py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_UART1EN) uart.Bus.CR1.Set(0) @@ -38,8 +40,9 @@ func handleUART1Interrupt(interrupt.Interrupt) { } func (uart *UART) writeByte(c byte) error { - retries := uartTXRetries + retries := uart.txRetries for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 { + uartYield() retries-- } if retries <= 0 { @@ -50,8 +53,9 @@ func (uart *UART) writeByte(c byte) error { } func (uart *UART) flush() { - retries := uartTXRetries + retries := uart.txRetries for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 { + uartYield() retries-- } } From c635bddafae1174fe72ebabd191ad5293202ed14 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:53:19 +0200 Subject: [PATCH 43/62] machine/py32: configure UART pins from UARTConfig --- make/smoketest.mk | 6 +++ src/machine/board_embedfire_py32f002b.go | 12 +++-- src/machine/board_embedfire_py32f030.go | 12 +++-- src/machine/machine_py32_uart.go | 8 +-- src/machine/machine_py32_uart2.go | 2 +- src/machine/machine_py32_uart_common.go | 33 ++++++++++++- .../machine_py32_uart_no_default_pins.go | 4 +- src/machine/machine_py32_uart_pinmap_f002b.go | 24 +++++++++ .../machine_py32_uart_pinmap_f003_f030.go | 49 +++++++++++++++++++ src/machine/machine_py32_uart_pinmap_none.go | 7 +++ src/machine/machine_py32_uart_type.go | 7 ++- testdata/py32-uart/f002b.go | 12 +++++ testdata/py32-uart/f003_f030.go | 16 ++++++ testdata/py32-uart/main.go | 5 ++ 14 files changed, 178 insertions(+), 19 deletions(-) create mode 100644 src/machine/machine_py32_uart_pinmap_f002b.go create mode 100644 src/machine/machine_py32_uart_pinmap_f003_f030.go create mode 100644 src/machine/machine_py32_uart_pinmap_none.go create mode 100644 testdata/py32-uart/f002b.go create mode 100644 testdata/py32-uart/f003_f030.go create mode 100644 testdata/py32-uart/main.go diff --git a/make/smoketest.mk b/make/smoketest.mk index d313908d74..303ae472c7 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -415,6 +415,12 @@ ifneq ($(PY32), 0) @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=embedfire-py32f002b examples/echo @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f002bx5 ./testdata/py32-uart + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f003x6 ./testdata/py32-uart + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f030x8 ./testdata/py32-uart + @$(MD5SUM) $(SMOKE_OUT).hex endif smoketest-avr: SMOKE_OUT = build/smoke/avr diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go index ce6b7886a9..db44fd4d62 100644 --- a/src/machine/board_embedfire_py32f002b.go +++ b/src/machine/board_embedfire_py32f002b.go @@ -18,9 +18,11 @@ const ( KEY2 = PA0 ) -func configureDefaultUARTPins() { - PA6.Configure(PinConfig{Mode: PinAlternate}) - PA6.SetAltFunc(1) - PA7.Configure(PinConfig{Mode: PinAlternate}) - PA7.SetAltFunc(3) +const ( + UART_TX_PIN = PA6 + UART_RX_PIN = PA7 +) + +func defaultUARTPins() (Pin, Pin) { + return UART_TX_PIN, UART_RX_PIN } diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go index f6d5bbe434..73c7f94373 100644 --- a/src/machine/board_embedfire_py32f030.go +++ b/src/machine/board_embedfire_py32f030.go @@ -18,9 +18,11 @@ const ( KEY2 = PA6 ) -func configureDefaultUARTPins() { - PA7.Configure(PinConfig{Mode: PinAlternate}) - PA7.SetAltFunc(8) - PA8.Configure(PinConfig{Mode: PinAlternate}) - PA8.SetAltFunc(8) +const ( + UART_TX_PIN = PA7 + UART_RX_PIN = PA8 +) + +func defaultUARTPins() (Pin, Pin) { + return UART_TX_PIN, UART_RX_PIN } diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go index 4fade009b3..3d358cd7cf 100644 --- a/src/machine/machine_py32_uart.go +++ b/src/machine/machine_py32_uart.go @@ -17,10 +17,11 @@ type UART struct { irq interrupt.Interrupt setup func(*UART) txRetries uint32 + num uint8 } // DefaultUART is the first USART (USART1) and backs machine.Serial. -var DefaultUART = &UART{Bus: defaultUSART(), Buffer: NewRingBuffer(), setup: setupUSART1} +var DefaultUART = &UART{Bus: defaultUSART(), Buffer: NewRingBuffer(), setup: setupUSART1, num: 1} func (uart *UART) Configure(config UARTConfig) error { @@ -28,6 +29,9 @@ func (uart *UART) Configure(config UARTConfig) error { config.BaudRate = 115200 } uart.txRetries = uartTXRetryBudget(config.BaudRate) + if err := configureUARTPins(uart.num, config); err != nil { + return err + } // Enable the peripheral clock and hook its RX interrupt. uart.setup(uart) @@ -46,8 +50,6 @@ func (uart *UART) Configure(config UARTConfig) error { // Enable transmitter, receiver, RX interrupt, and the peripheral. uart.Bus.CR1.Set(py32.USART_CR1_TE | py32.USART_CR1_RE | py32.USART_CR1_RXNEIE | py32.USART_CR1_UE) - configureDefaultUARTPins() - return nil } diff --git a/src/machine/machine_py32_uart2.go b/src/machine/machine_py32_uart2.go index 12db23a464..1ffe196dfe 100644 --- a/src/machine/machine_py32_uart2.go +++ b/src/machine/machine_py32_uart2.go @@ -10,7 +10,7 @@ import ( // UART2 is the second USART (USART2), available on PY32 parts that provide it. // It shares the generic UART driver; its clock gate and interrupt are wired up // by setupUSART2. -var UART2 = &UART{Bus: py32.USART2, Buffer: NewRingBuffer(), setup: setupUSART2} +var UART2 = &UART{Bus: py32.USART2, Buffer: NewRingBuffer(), setup: setupUSART2, num: 2} // setupUSART2 enables the USART2 peripheral clock and installs its RX interrupt // handler. diff --git a/src/machine/machine_py32_uart_common.go b/src/machine/machine_py32_uart_common.go index 5f6a37caa7..4429fd144e 100644 --- a/src/machine/machine_py32_uart_common.go +++ b/src/machine/machine_py32_uart_common.go @@ -10,7 +10,38 @@ type uartError string func (e uartError) Error() string { return string(e) } -const errUARTWriteTimeout uartError = "UART: write timeout" +const ( + errUARTWriteTimeout uartError = "UART: write timeout" + errUARTInvalidTXPin uartError = "UART: invalid TX pin" + errUARTInvalidRXPin uartError = "UART: invalid RX pin" + errUARTPinsEqual uartError = "UART: TX and RX pins must differ" +) + +func configureUARTPins(uartNum uint8, config UARTConfig) error { + if config.TX == 0 && config.RX == 0 { + config.TX, config.RX = defaultUARTPins() + } + if config.TX == config.RX && config.TX != NoPin { + return errUARTPinsEqual + } + if config.TX != NoPin { + af, ok := uartPinAF(uartNum, config.TX, true) + if !ok { + return errUARTInvalidTXPin + } + config.TX.Configure(PinConfig{Mode: PinAlternate}) + config.TX.SetAltFunc(af) + } + if config.RX != NoPin { + af, ok := uartPinAF(uartNum, config.RX, false) + if !ok { + return errUARTInvalidRXPin + } + config.RX.Configure(PinConfig{Mode: PinAlternate}) + config.RX.SetAltFunc(af) + } + return nil +} func uartTXRetryBudget(baudRate uint32) uint32 { retries := CPUFrequency() / baudRate * 10 diff --git a/src/machine/machine_py32_uart_no_default_pins.go b/src/machine/machine_py32_uart_no_default_pins.go index d88ff9b108..8d7ed8387d 100644 --- a/src/machine/machine_py32_uart_no_default_pins.go +++ b/src/machine/machine_py32_uart_no_default_pins.go @@ -2,6 +2,6 @@ package machine -func configureDefaultUARTPins() { - // There are no default UART pins for this target. +func defaultUARTPins() (Pin, Pin) { + return NoPin, NoPin } diff --git a/src/machine/machine_py32_uart_pinmap_f002b.go b/src/machine/machine_py32_uart_pinmap_f002b.go new file mode 100644 index 0000000000..7971b88df1 --- /dev/null +++ b/src/machine/machine_py32_uart_pinmap_f002b.go @@ -0,0 +1,24 @@ +//go:build py32 && py32f002bxx + +package machine + +// PY32F002B datasheet tables 3-4 and 3-5. +func uartPinAF(uartNum uint8, pin Pin, tx bool) (uint8, bool) { + if uartNum != 1 { + return 0, false + } + if tx { + switch pin { + case PA3, PA6, PA7, PB4, PB6: + return 1, true + } + } else { + switch pin { + case PA2, PA4, PB5: + return 1, true + case PA7: + return 3, true + } + } + return 0, false +} diff --git a/src/machine/machine_py32_uart_pinmap_f003_f030.go b/src/machine/machine_py32_uart_pinmap_f003_f030.go new file mode 100644 index 0000000000..5fb41f7916 --- /dev/null +++ b/src/machine/machine_py32_uart_pinmap_f003_f030.go @@ -0,0 +1,49 @@ +//go:build py32 && (py32f003xx || py32f030xx) + +package machine + +// PY32F003 datasheet tables 3-6 through 3-8 and PY32F030 datasheet +// tables 3-1 through 3-3. +func uartPinAF(uartNum uint8, pin Pin, tx bool) (uint8, bool) { + switch uartNum { + case 1: + if tx { + switch pin { + case PB6, PF3: + return 0, true + case PA2, PA9, PA14: + return 1, true + case PA7, PA10, PB8, PF1: + return 8, true + } + } else { + switch pin { + case PB2, PB7: + return 0, true + case PA3, PA10, PA15: + return 1, true + case PA8, PA9, PA13, PF0: + return 8, true + } + } + case 2: + if tx { + switch pin { + case PA2, PA9, PA14, PB6, PB8, PF1, PF3: + return 4, true + case PA0, PA4, PA7, PF0: + return 9, true + } + } else { + switch pin { + case PB2: + return 3, true + case PA3, PA10, PA15, PB7, PF0, PF2: + return 4, true + case PA1, PA5, PA8, PF1: + return 9, true + } + } + } + return 0, false +} diff --git a/src/machine/machine_py32_uart_pinmap_none.go b/src/machine/machine_py32_uart_pinmap_none.go new file mode 100644 index 0000000000..ce2633ec4c --- /dev/null +++ b/src/machine/machine_py32_uart_pinmap_none.go @@ -0,0 +1,7 @@ +//go:build py32 && !py32f002bxx && !py32f003xx && !py32f030xx + +package machine + +func uartPinAF(uartNum uint8, pin Pin, tx bool) (uint8, bool) { + return 0, false +} diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go index 9b69cf5eae..f4a520373c 100644 --- a/src/machine/machine_py32_uart_type.go +++ b/src/machine/machine_py32_uart_type.go @@ -12,15 +12,19 @@ type UART struct { Buffer *RingBuffer irq interrupt.Interrupt txRetries uint32 + num uint8 } -var DefaultUART = &UART{Bus: py32.UART1, Buffer: NewRingBuffer()} +var DefaultUART = &UART{Bus: py32.UART1, Buffer: NewRingBuffer(), num: 1} func (uart *UART) Configure(config UARTConfig) error { if config.BaudRate == 0 { config.BaudRate = 115200 } uart.txRetries = uartTXRetryBudget(config.BaudRate) + if err := configureUARTPins(uart.num, config); err != nil { + return err + } py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_UART1EN) uart.Bus.CR1.Set(0) @@ -31,7 +35,6 @@ func (uart *UART) Configure(config UARTConfig) error { uart.irq = interrupt.New(py32.IRQ_UART1, handleUART1Interrupt) uart.irq.SetPriority(0xc0) uart.irq.Enable() - configureDefaultUARTPins() return nil } diff --git a/testdata/py32-uart/f002b.go b/testdata/py32-uart/f002b.go new file mode 100644 index 0000000000..2bfa45a658 --- /dev/null +++ b/testdata/py32-uart/f002b.go @@ -0,0 +1,12 @@ +//go:build py32f002bxx + +package main + +import "machine" + +func configureUARTs() { + _ = machine.DefaultUART.Configure(machine.UARTConfig{ + TX: machine.PA3, + RX: machine.PA4, + }) +} diff --git a/testdata/py32-uart/f003_f030.go b/testdata/py32-uart/f003_f030.go new file mode 100644 index 0000000000..175c139714 --- /dev/null +++ b/testdata/py32-uart/f003_f030.go @@ -0,0 +1,16 @@ +//go:build py32f003xx || py32f030xx + +package main + +import "machine" + +func configureUARTs() { + _ = machine.DefaultUART.Configure(machine.UARTConfig{ + TX: machine.PA2, + RX: machine.PA3, + }) + _ = machine.UART2.Configure(machine.UARTConfig{ + TX: machine.PA0, + RX: machine.PA1, + }) +} diff --git a/testdata/py32-uart/main.go b/testdata/py32-uart/main.go new file mode 100644 index 0000000000..7442baa026 --- /dev/null +++ b/testdata/py32-uart/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + configureUARTs() +} From ad9002d63c0d71ece584bea4befacd946894de65 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 00:54:36 +0200 Subject: [PATCH 44/62] build: use the current PY32 SVD repository URL --- make/gen-device.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/gen-device.mk b/make/gen-device.mk index 9f3c5cf972..135879385c 100644 --- a/make/gen-device.mk +++ b/make/gen-device.mk @@ -60,7 +60,7 @@ gen-device-renesas: build/gen-device-svd GO111MODULE=off $(GO) fmt ./src/device/renesas gen-device-py32: build/gen-device-svd - ./build/gen-device-svd -source=https://github.com/tinygo-org/py32-svd lib/py32-svd/svd src/device/py32/ + ./build/gen-device-svd -source=https://github.com/burgrp/py32-svd lib/py32-svd/svd src/device/py32/ GO111MODULE=off $(GO) fmt ./src/device/py32 gen-target-py32: ## Generate PY32 target and linker definitions From 98a2d1bed2a0cdebefadec247ae70222dce8034d Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 01:01:15 +0200 Subject: [PATCH 45/62] test: cover PY32 UART register layouts --- make/smoketest.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/make/smoketest.mk b/make/smoketest.mk index 303ae472c7..c6501a165b 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -421,6 +421,14 @@ ifneq ($(PY32), 0) @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f030x8 ./testdata/py32-uart @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f403xb examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32e407xc examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f410xb examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32t020x5 examples/echo + @$(MD5SUM) $(SMOKE_OUT).hex endif smoketest-avr: SMOKE_OUT = build/smoke/avr From fe40cc7d01e8fb75376d7278cb9c471950460016 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 10:37:53 +0200 Subject: [PATCH 46/62] machine/py32: restore dynamic CPU frequency tracking --- make/smoketest.mk | 4 ++++ src/machine/machine_py32_clock.go | 10 +++++++++- src/machine/machine_py32_clock_24mhz.go | 2 +- src/machine/machine_py32_clock_8mhz.go | 2 +- testdata/py32-clock/main.go | 23 +++++++++++++++++++++++ tools/gen-py32-targets/README.md | 5 ++++- 6 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 testdata/py32-clock/main.go diff --git a/make/smoketest.mk b/make/smoketest.mk index c6501a165b..12ecc2ad8d 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -423,6 +423,10 @@ ifneq ($(PY32), 0) @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f403xb examples/echo @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f030x8 ./testdata/py32-clock + @$(MD5SUM) $(SMOKE_OUT).hex + $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f403xb ./testdata/py32-clock + @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32e407xc examples/echo @$(MD5SUM) $(SMOKE_OUT).hex $(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=py32f410xb examples/echo diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index 74b84c5ee7..30c87f569e 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,6 +2,14 @@ package machine +// CPUFrequencyHz is the current CPU frequency in hertz. +// +// Application code that changes the system clock through the RCC registers +// must update this value after the new clock is stable, then reconfigure +// SysTick and any peripherals derived from the system clock. Assigning this +// variable does not configure the clock hardware. +var CPUFrequencyHz uint32 = defaultCPUFrequencyHz + func CPUFrequency() uint32 { - return cpuFrequencyHz + return CPUFrequencyHz } diff --git a/src/machine/machine_py32_clock_24mhz.go b/src/machine/machine_py32_clock_24mhz.go index 08f2a69c58..a1e8a072de 100644 --- a/src/machine/machine_py32_clock_24mhz.go +++ b/src/machine/machine_py32_clock_24mhz.go @@ -2,4 +2,4 @@ package machine -const cpuFrequencyHz = 24_000_000 +const defaultCPUFrequencyHz = 24_000_000 diff --git a/src/machine/machine_py32_clock_8mhz.go b/src/machine/machine_py32_clock_8mhz.go index 88e9b8ef57..554e9fca8a 100644 --- a/src/machine/machine_py32_clock_8mhz.go +++ b/src/machine/machine_py32_clock_8mhz.go @@ -2,4 +2,4 @@ package machine -const cpuFrequencyHz = 8_000_000 +const defaultCPUFrequencyHz = 8_000_000 diff --git a/testdata/py32-clock/main.go b/testdata/py32-clock/main.go new file mode 100644 index 0000000000..aaa4db950c --- /dev/null +++ b/testdata/py32-clock/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "machine" + "runtime" + "runtime/interrupt" +) + +// The application must establish and stabilize the hardware clock before +// calling clockChanged. +func clockChanged(frequency uint32, uartConfig machine.UARTConfig) error { + state := interrupt.Disable() + + machine.CPUFrequencyHz = frequency + runtime.ConfigureSystemTimer() + err := machine.DefaultUART.Configure(uartConfig) + interrupt.Restore(state) + return err +} + +func main() { + _ = clockChanged(machine.CPUFrequency(), machine.UARTConfig{}) +} diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index 1adacd6bf4..9dd25a579e 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -49,4 +49,7 @@ every device. In particular, PY32F410 SVD interrupt metadata stops before the serial interrupts, so its default USART is configured without receive interrupts rather than assigning an unverified IRQ number. The M4 SVDs also do not expose the M0+ `ICSCR.HSI_FS` selector, so the runtime preserves their reset -clock configuration and reports the vendor-defined 8 MHz reset frequency. \ No newline at end of file +clock configuration and initially reports the vendor-defined 8 MHz reset +frequency. Applications that establish a different clock tree must update +`machine.CPUFrequencyHz`, then reconfigure SysTick and frequency-dependent +peripherals. \ No newline at end of file From 3d0ec81429c46a07e8825435b36c8600d883f007 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 20 Aug 2026 10:49:03 +0200 Subject: [PATCH 47/62] machine/py32: share the USART TX-ready bit --- src/machine/machine_py32_uart_data.go | 5 +++-- src/machine/machine_py32_uart_data_txe_txf.go | 21 ------------------- targets/py32f410xx.json | 1 - tools/gen-py32-targets/main.go | 2 -- tools/gen-py32-targets/main_test.go | 2 +- 5 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 src/machine/machine_py32_uart_data_txe_txf.go diff --git a/src/machine/machine_py32_uart_data.go b/src/machine/machine_py32_uart_data.go index bc4b89325b..3345e57700 100644 --- a/src/machine/machine_py32_uart_data.go +++ b/src/machine/machine_py32_uart_data.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_uart_type && !py32_usart_split_data && !py32_usart_txe_txf +//go:build py32 && !py32_uart_type && !py32_usart_split_data package machine @@ -13,7 +13,8 @@ func writeUSARTData(bus *py32.USART_Type, value uint32) { } func usartTXReady(bus *py32.USART_Type) bool { - return bus.SR.Get()&py32.USART_SR_TXE != 0 + const txEmpty = 1 << 7 // TXE or TXE_TXFNF, depending on the family. + return bus.SR.Get()&txEmpty != 0 } func usartTXComplete(bus *py32.USART_Type) bool { diff --git a/src/machine/machine_py32_uart_data_txe_txf.go b/src/machine/machine_py32_uart_data_txe_txf.go deleted file mode 100644 index 8a64150dae..0000000000 --- a/src/machine/machine_py32_uart_data_txe_txf.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build py32 && !py32_uart_type && !py32_usart_split_data && py32_usart_txe_txf - -package machine - -import "device/py32" - -func readUSARTData(bus *py32.USART_Type) uint32 { - return bus.DR.Get() -} - -func writeUSARTData(bus *py32.USART_Type, value uint32) { - bus.DR.Set(value) -} - -func usartTXReady(bus *py32.USART_Type) bool { - return bus.SR.Get()&py32.USART_SR_TXE_TXFNF != 0 -} - -func usartTXComplete(bus *py32.USART_Type) bool { - return bus.SR.Get()&py32.USART_SR_TC != 0 -} diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json index 6e7140562e..154465b63e 100644 --- a/targets/py32f410xx.json +++ b/targets/py32f410xx.json @@ -8,7 +8,6 @@ "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", - "py32_usart_txe_txf", "py32_uart_clock_apb2", "py32_uart_no_interrupt" ], diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 173aaf6ae6..3602fa0401 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -59,7 +59,6 @@ var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") var usartUnnumbered = familySet("py32f410xx") -var usartTXETXF = familySet("py32f410xx") var usart1ClockLiteral = familySet("py32f001cxx", "py32f001xx") var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartNoInterrupt = familySet("py32f410xx") @@ -89,7 +88,6 @@ func familyBuildTags(family string) []string { {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, {"py32_usart_unnumbered", usartUnnumbered}, - {"py32_usart_txe_txf", usartTXETXF}, {"py32_usart1_clock_literal", usart1ClockLiteral}, {"py32_uart_clock_apb2", uartClockAPB2}, {"py32_uart_no_interrupt", uartNoInterrupt}, diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index f3b6a9ad8c..d58c5d4e20 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -63,7 +63,7 @@ func TestGenerate(t *testing.T) { checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") - checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_usart_txe_txf", "py32_uart_clock_apb2", "py32_uart_no_interrupt") + checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) From 1792004a13288bf0266728196bfcf37106b030a8 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 21 Aug 2026 01:13:06 +0200 Subject: [PATCH 48/62] targets/py32: scale system stacks with RAM --- targets/py32e407xc.ld | 2 +- targets/py32e407xd.ld | 2 +- targets/py32e407xe.ld | 2 +- targets/py32f001cx4.ld | 2 +- targets/py32f002ax5.ld | 7 +++-- targets/py32f002bx5.ld | 7 +++-- targets/py32f002cx5.ld | 2 +- targets/py32f002xx2.ld | 2 +- targets/py32f002xx4.ld | 2 +- targets/py32f002xx5.ld | 2 +- targets/py32f002zx4.ld | 2 +- targets/py32f003x4.ld | 7 +++-- targets/py32f003x6.ld | 7 +++-- targets/py32f003x7.ld | 7 +++-- targets/py32f003x8.ld | 7 +++-- targets/py32f021x8.ld | 2 +- targets/py32f030x4.ld | 7 +++-- targets/py32f030x6.ld | 7 +++-- targets/py32f030x7.ld | 7 +++-- targets/py32f030x8.ld | 9 +++---- targets/py32f031x4.ld | 2 +- targets/py32f031x6.ld | 2 +- targets/py32f031x7.ld | 2 +- targets/py32f031x8.ld | 2 +- targets/py32f032x8.ld | 2 +- targets/py32f040cx6.ld | 2 +- targets/py32f040cx8.ld | 2 +- targets/py32f040cx9.ld | 2 +- targets/py32f040cxb.ld | 2 +- targets/py32f040epxb.ld | 2 +- targets/py32f040ex6.ld | 2 +- targets/py32f040ex8.ld | 2 +- targets/py32f040ex9.ld | 2 +- targets/py32f040exb.ld | 2 +- targets/py32f040x6.ld | 2 +- targets/py32f040x8.ld | 2 +- targets/py32f040x9.ld | 2 +- targets/py32f040xb.ld | 2 +- targets/py32f071cx6.ld | 2 +- targets/py32f071cx8.ld | 2 +- targets/py32f071cx9.ld | 2 +- targets/py32f071cxb.ld | 2 +- targets/py32f071ex6.ld | 2 +- targets/py32f071ex8.ld | 2 +- targets/py32f071ex9.ld | 2 +- targets/py32f071exb.ld | 2 +- targets/py32f071x6.ld | 2 +- targets/py32f071x8.ld | 2 +- targets/py32f071x9.ld | 2 +- targets/py32f071xb.ld | 2 +- targets/py32f072cx6.ld | 2 +- targets/py32f072cx8.ld | 2 +- targets/py32f072cx9.ld | 2 +- targets/py32f072cxb.ld | 2 +- targets/py32f072ex6.ld | 2 +- targets/py32f072ex8.ld | 2 +- targets/py32f072ex9.ld | 2 +- targets/py32f072exb.ld | 2 +- targets/py32f072x6.ld | 2 +- targets/py32f072x8.ld | 2 +- targets/py32f072x9.ld | 2 +- targets/py32f072xb.ld | 2 +- targets/py32f403xb.ld | 2 +- targets/py32f403xc.ld | 2 +- targets/py32f403xd.ld | 2 +- targets/py32f410xb.ld | 2 +- targets/py32l020x5.ld | 2 +- targets/py32l090xb.ld | 2 +- targets/py32l090xc.ld | 2 +- targets/py32m010x5.ld | 2 +- targets/py32m020x6.ld | 2 +- targets/py32m030x8.ld | 2 +- targets/py32m031x8.ld | 2 +- targets/py32m070cxb.ld | 2 +- targets/py32m070xb.ld | 2 +- targets/py32md310x8.ld | 2 +- targets/py32md320x8.ld | 2 +- targets/py32md410x8.ld | 2 +- targets/py32md420x8.ld | 2 +- targets/py32md430x8.ld | 2 +- targets/py32t020bx5.ld | 2 +- targets/py32t020bx6.ld | 2 +- targets/py32t020x5.ld | 2 +- targets/py32t020x6.ld | 2 +- targets/py32t090xb.ld | 2 +- targets/py32t090xc.ld | 2 +- targets/py32t092xc.ld | 2 +- tools/gen-py32-targets/README.md | 15 ++++++++--- tools/gen-py32-targets/main.go | 40 +++++++++++++++++++---------- tools/gen-py32-targets/main_test.go | 39 +++++++++++++++++++++++++--- 90 files changed, 181 insertions(+), 139 deletions(-) diff --git a/targets/py32e407xc.ld b/targets/py32e407xc.ld index ed238cc140..0d72cb3d6b 100644 --- a/targets/py32e407xc.ld +++ b/targets/py32e407xc.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1c000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32e407xd.ld b/targets/py32e407xd.ld index 7bead5c559..c2cb9cb8cb 100644 --- a/targets/py32e407xd.ld +++ b/targets/py32e407xd.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32e407xe.ld b/targets/py32e407xe.ld index aaa1b18201..ff1e0e6eca 100644 --- a/targets/py32e407xe.ld +++ b/targets/py32e407xe.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f001cx4.ld b/targets/py32f001cx4.ld index 57223aed5f..ff5b46251c 100644 --- a/targets/py32f001cx4.ld +++ b/targets/py32f001cx4.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002ax5.ld b/targets/py32f002ax5.ld index 766850cc45..997e8861a9 100644 --- a/targets/py32f002ax5.ld +++ b/targets/py32f002ax5.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 20K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 3K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x5000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002bx5.ld b/targets/py32f002bx5.ld index dde2f066e9..f0d8e67602 100644 --- a/targets/py32f002bx5.ld +++ b/targets/py32f002bx5.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 24K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 3K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002cx5.ld b/targets/py32f002cx5.ld index 8ddf5c7d92..3fe1a37288 100644 --- a/targets/py32f002cx5.ld +++ b/targets/py32f002cx5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xx2.ld b/targets/py32f002xx2.ld index 2e1baf059c..2406c1bdba 100644 --- a/targets/py32f002xx2.ld +++ b/targets/py32f002xx2.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xx4.ld b/targets/py32f002xx4.ld index 57223aed5f..ff5b46251c 100644 --- a/targets/py32f002xx4.ld +++ b/targets/py32f002xx4.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002xx5.ld b/targets/py32f002xx5.ld index 0a5ac0125b..f0d8e67602 100644 --- a/targets/py32f002xx5.ld +++ b/targets/py32f002xx5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f002zx4.ld b/targets/py32f002zx4.ld index 57223aed5f..ff5b46251c 100644 --- a/targets/py32f002zx4.ld +++ b/targets/py32f002zx4.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x4.ld b/targets/py32f003x4.ld index 71f4b877c4..3f9d35453d 100644 --- a/targets/py32f003x4.ld +++ b/targets/py32f003x4.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x6.ld b/targets/py32f003x6.ld index 56ef9222f5..36be015b7f 100644 --- a/targets/py32f003x6.ld +++ b/targets/py32f003x6.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x7.ld b/targets/py32f003x7.ld index 9493be4cf1..63dd4310aa 100644 --- a/targets/py32f003x7.ld +++ b/targets/py32f003x7.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 48K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0xc000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f003x8.ld b/targets/py32f003x8.ld index c0b64037cf..7e7e6b6b50 100644 --- a/targets/py32f003x8.ld +++ b/targets/py32f003x8.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 64K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f021x8.ld b/targets/py32f021x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f021x8.ld +++ b/targets/py32f021x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x4.ld b/targets/py32f030x4.ld index 71f4b877c4..3f9d35453d 100644 --- a/targets/py32f030x4.ld +++ b/targets/py32f030x4.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 16K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x6.ld b/targets/py32f030x6.ld index 56ef9222f5..36be015b7f 100644 --- a/targets/py32f030x6.ld +++ b/targets/py32f030x6.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 32K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x7.ld b/targets/py32f030x7.ld index 9493be4cf1..63dd4310aa 100644 --- a/targets/py32f030x7.ld +++ b/targets/py32f030x7.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 48K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0xc000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f030x8.ld b/targets/py32f030x8.ld index 380a4d3811..7e7e6b6b50 100644 --- a/targets/py32f030x8.ld +++ b/targets/py32f030x8.ld @@ -1,10 +1,9 @@ - MEMORY { - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 64K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K + FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000 + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; -INCLUDE "targets/arm.ld" \ No newline at end of file +INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x4.ld b/targets/py32f031x4.ld index 5b4e711e97..3f9d35453d 100644 --- a/targets/py32f031x4.ld +++ b/targets/py32f031x4.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x6.ld b/targets/py32f031x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f031x6.ld +++ b/targets/py32f031x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x7.ld b/targets/py32f031x7.ld index 50b0ef43be..63dd4310aa 100644 --- a/targets/py32f031x7.ld +++ b/targets/py32f031x7.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f031x8.ld b/targets/py32f031x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f031x8.ld +++ b/targets/py32f031x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f032x8.ld b/targets/py32f032x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f032x8.ld +++ b/targets/py32f032x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cx6.ld b/targets/py32f040cx6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f040cx6.ld +++ b/targets/py32f040cx6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cx8.ld b/targets/py32f040cx8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f040cx8.ld +++ b/targets/py32f040cx8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cx9.ld b/targets/py32f040cx9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f040cx9.ld +++ b/targets/py32f040cx9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040cxb.ld b/targets/py32f040cxb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f040cxb.ld +++ b/targets/py32f040cxb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040epxb.ld b/targets/py32f040epxb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f040epxb.ld +++ b/targets/py32f040epxb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040ex6.ld b/targets/py32f040ex6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f040ex6.ld +++ b/targets/py32f040ex6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040ex8.ld b/targets/py32f040ex8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f040ex8.ld +++ b/targets/py32f040ex8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040ex9.ld b/targets/py32f040ex9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f040ex9.ld +++ b/targets/py32f040ex9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040exb.ld b/targets/py32f040exb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f040exb.ld +++ b/targets/py32f040exb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040x6.ld b/targets/py32f040x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f040x6.ld +++ b/targets/py32f040x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040x8.ld b/targets/py32f040x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f040x8.ld +++ b/targets/py32f040x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040x9.ld b/targets/py32f040x9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f040x9.ld +++ b/targets/py32f040x9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f040xb.ld b/targets/py32f040xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f040xb.ld +++ b/targets/py32f040xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cx6.ld b/targets/py32f071cx6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f071cx6.ld +++ b/targets/py32f071cx6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cx8.ld b/targets/py32f071cx8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f071cx8.ld +++ b/targets/py32f071cx8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cx9.ld b/targets/py32f071cx9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f071cx9.ld +++ b/targets/py32f071cx9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071cxb.ld b/targets/py32f071cxb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f071cxb.ld +++ b/targets/py32f071cxb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071ex6.ld b/targets/py32f071ex6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f071ex6.ld +++ b/targets/py32f071ex6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071ex8.ld b/targets/py32f071ex8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f071ex8.ld +++ b/targets/py32f071ex8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071ex9.ld b/targets/py32f071ex9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f071ex9.ld +++ b/targets/py32f071ex9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071exb.ld b/targets/py32f071exb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f071exb.ld +++ b/targets/py32f071exb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071x6.ld b/targets/py32f071x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f071x6.ld +++ b/targets/py32f071x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071x8.ld b/targets/py32f071x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f071x8.ld +++ b/targets/py32f071x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071x9.ld b/targets/py32f071x9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f071x9.ld +++ b/targets/py32f071x9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f071xb.ld b/targets/py32f071xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f071xb.ld +++ b/targets/py32f071xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cx6.ld b/targets/py32f072cx6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f072cx6.ld +++ b/targets/py32f072cx6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cx8.ld b/targets/py32f072cx8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f072cx8.ld +++ b/targets/py32f072cx8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cx9.ld b/targets/py32f072cx9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f072cx9.ld +++ b/targets/py32f072cx9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072cxb.ld b/targets/py32f072cxb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f072cxb.ld +++ b/targets/py32f072cxb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072ex6.ld b/targets/py32f072ex6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f072ex6.ld +++ b/targets/py32f072ex6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072ex8.ld b/targets/py32f072ex8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f072ex8.ld +++ b/targets/py32f072ex8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072ex9.ld b/targets/py32f072ex9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f072ex9.ld +++ b/targets/py32f072ex9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072exb.ld b/targets/py32f072exb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f072exb.ld +++ b/targets/py32f072exb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072x6.ld b/targets/py32f072x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32f072x6.ld +++ b/targets/py32f072x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072x8.ld b/targets/py32f072x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32f072x8.ld +++ b/targets/py32f072x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072x9.ld b/targets/py32f072x9.ld index 0294af6aa8..16b6fea7cf 100644 --- a/targets/py32f072x9.ld +++ b/targets/py32f072x9.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x3000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f072xb.ld b/targets/py32f072xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f072xb.ld +++ b/targets/py32f072xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xb.ld b/targets/py32f403xb.ld index bbe5cb507b..db51c3aec1 100644 --- a/targets/py32f403xb.ld +++ b/targets/py32f403xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xc.ld b/targets/py32f403xc.ld index 643ff1c887..32c6af6ada 100644 --- a/targets/py32f403xc.ld +++ b/targets/py32f403xc.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f403xd.ld b/targets/py32f403xd.ld index 7a3906ed69..902852917a 100644 --- a/targets/py32f403xd.ld +++ b/targets/py32f403xd.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x10000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32f410xb.ld b/targets/py32f410xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32f410xb.ld +++ b/targets/py32f410xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32l020x5.ld b/targets/py32l020x5.ld index 0a5ac0125b..f0d8e67602 100644 --- a/targets/py32l020x5.ld +++ b/targets/py32l020x5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32l090xb.ld b/targets/py32l090xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32l090xb.ld +++ b/targets/py32l090xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32l090xc.ld b/targets/py32l090xc.ld index 1370797646..69587e3c5b 100644 --- a/targets/py32l090xc.ld +++ b/targets/py32l090xc.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m010x5.ld b/targets/py32m010x5.ld index 0a5ac0125b..f0d8e67602 100644 --- a/targets/py32m010x5.ld +++ b/targets/py32m010x5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m020x6.ld b/targets/py32m020x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32m020x6.ld +++ b/targets/py32m020x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m030x8.ld b/targets/py32m030x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32m030x8.ld +++ b/targets/py32m030x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m031x8.ld b/targets/py32m031x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32m031x8.ld +++ b/targets/py32m031x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m070cxb.ld b/targets/py32m070cxb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32m070cxb.ld +++ b/targets/py32m070cxb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32m070xb.ld b/targets/py32m070xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32m070xb.ld +++ b/targets/py32m070xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32md310x8.ld b/targets/py32md310x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32md310x8.ld +++ b/targets/py32md310x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32md320x8.ld b/targets/py32md320x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32md320x8.ld +++ b/targets/py32md320x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32md410x8.ld b/targets/py32md410x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32md410x8.ld +++ b/targets/py32md410x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32md420x8.ld b/targets/py32md420x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32md420x8.ld +++ b/targets/py32md420x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32md430x8.ld b/targets/py32md430x8.ld index bcf3f555b3..7e7e6b6b50 100644 --- a/targets/py32md430x8.ld +++ b/targets/py32md430x8.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t020bx5.ld b/targets/py32t020bx5.ld index bf4b1999c5..25062ef741 100644 --- a/targets/py32t020bx5.ld +++ b/targets/py32t020bx5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t020bx6.ld b/targets/py32t020bx6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32t020bx6.ld +++ b/targets/py32t020bx6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t020x5.ld b/targets/py32t020x5.ld index bf4b1999c5..25062ef741 100644 --- a/targets/py32t020x5.ld +++ b/targets/py32t020x5.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t020x6.ld b/targets/py32t020x6.ld index 8012cccc6c..36be015b7f 100644 --- a/targets/py32t020x6.ld +++ b/targets/py32t020x6.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000 } -_stack_size = 512; +_stack_size = 1K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t090xb.ld b/targets/py32t090xb.ld index 941f23a0cc..6cb6a79360 100644 --- a/targets/py32t090xb.ld +++ b/targets/py32t090xb.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x4000 } -_stack_size = 512; +_stack_size = 2K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t090xc.ld b/targets/py32t090xc.ld index 1370797646..69587e3c5b 100644 --- a/targets/py32t090xc.ld +++ b/targets/py32t090xc.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/targets/py32t092xc.ld b/targets/py32t092xc.ld index 1370797646..69587e3c5b 100644 --- a/targets/py32t092xc.ld +++ b/targets/py32t092xc.ld @@ -4,6 +4,6 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x8000 } -_stack_size = 512; +_stack_size = 4K; INCLUDE "targets/arm.ld" diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index 9dd25a579e..0a9c7df3bd 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -35,10 +35,17 @@ registers, `USART` versus `UART` blocks, split USART receive/transmit data registers, and HSI selector availability. Keep these classifications in the target generator rather than adding long family expressions to machine files. -Existing PY32 target files are retained for compatibility. In particular, their -established aliases and flashing commands are not regenerated. Newly generated -targets intentionally omit flashing commands because a compatible programmer -identifier has not been verified for every Puya part. +Existing PY32 target JSON files are retained for compatibility. In particular, +their established aliases and flashing commands are not regenerated. Linker +scripts are generated for every concrete target so memory definitions and stack +sizes remain consistent. Newly generated targets intentionally omit flashing +commands because a compatible programmer identifier has not been verified for +every Puya part. + +The system and interrupt stack is sized from available RAM: targets with up to +4 KiB use 1 KiB, targets with up to 16 KiB use 2 KiB, and larger targets use +4 KiB. This linker-defined stack is distinct from goroutine fallback stacks +selected by TinyGo's `--stack-size` option. ## Machine support status diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 3602fa0401..412fea2ea7 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -100,9 +100,10 @@ func familyBuildTags(family string) []string { return tags } -var legacyTargets = map[string]bool{ - // Keep pre-existing definitions, including established aliases and flashing - // commands. New definitions intentionally contain no flashing command. +var legacyTargetJSON = map[string]bool{ + // Keep pre-existing JSON definitions, including established aliases and + // flashing commands. Their linker scripts are still generated from the + // normalized device table. "py32f002ax5": true, "py32f002bx5": true, "py32f003x4": true, @@ -184,6 +185,17 @@ func readDevices(path string) ([]device, error) { return devices, nil } +func systemStackSize(ramSize uint64) uint64 { + switch { + case ramSize <= 4*1024: + return 1024 + case ramSize <= 16*1024: + return 2 * 1024 + default: + return 4 * 1024 + } +} + func generate(out string, devices []device) error { if err := os.MkdirAll(out, 0o755); err != nil { return err @@ -220,18 +232,18 @@ func generate(out string, devices []device) error { } for _, device := range devices { - if legacyTargets[device.Part] { - continue - } - spec := target{ - Inherits: []string{device.Family}, - BuildTags: []string{device.Part}, - LinkerScript: "targets/" + device.Part + ".ld", - } - if err := writeJSON(filepath.Join(out, device.Part+".json"), spec); err != nil { - return err + if !legacyTargetJSON[device.Part] { + spec := target{ + Inherits: []string{device.Family}, + BuildTags: []string{device.Part}, + LinkerScript: "targets/" + device.Part + ".ld", + } + if err := writeJSON(filepath.Join(out, device.Part+".json"), spec); err != nil { + return err + } } - linker := fmt.Sprintf("MEMORY\n{\n FLASH_TEXT (rx) : ORIGIN = %#x, LENGTH = %#x\n RAM (xrw) : ORIGIN = %#x, LENGTH = %#x\n}\n\n_stack_size = 512;\n\nINCLUDE \"targets/arm.ld\"\n", device.FlashStart, device.FlashSize, device.RAMStart, device.RAMSize) + stackSize := systemStackSize(device.RAMSize) + linker := fmt.Sprintf("MEMORY\n{\n FLASH_TEXT (rx) : ORIGIN = %#x, LENGTH = %#x\n RAM (xrw) : ORIGIN = %#x, LENGTH = %#x\n}\n\n_stack_size = %dK;\n\nINCLUDE \"targets/arm.ld\"\n", device.FlashStart, device.FlashSize, device.RAMStart, device.RAMSize, stackSize/1024) if err := os.WriteFile(filepath.Join(out, device.Part+".ld"), []byte(linker), 0o644); err != nil { return err } diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index d58c5d4e20..760133fb40 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -36,6 +36,25 @@ func TestDeviceTable(t *testing.T) { } } +func TestSystemStackSize(t *testing.T) { + tests := []struct { + ramSize uint64 + want uint64 + }{ + {2 * 1024, 1024}, + {4 * 1024, 1024}, + {4*1024 + 1, 2 * 1024}, + {16 * 1024, 2 * 1024}, + {16*1024 + 1, 4 * 1024}, + {144 * 1024, 4 * 1024}, + } + for _, test := range tests { + if got := systemStackSize(test.ramSize); got != test.want { + t.Errorf("systemStackSize(%d) = %d, want %d", test.ramSize, got, test.want) + } + } +} + func TestGenerate(t *testing.T) { devices, err := readDevices("devices.csv") if err != nil { @@ -50,9 +69,9 @@ func TestGenerate(t *testing.T) { if err != nil { t.Fatal(err) } - // 41 family JSON files plus JSON and linker files for the 77 non-legacy - // concrete targets. - if got, want := len(entries), 195; got != want { + // 41 family JSON files, 77 generated concrete JSON files, and linker + // scripts for all 87 concrete targets. + if got, want := len(entries), 205; got != want { t.Fatalf("generated %d files, want %d", got, want) } @@ -77,6 +96,20 @@ func TestGenerate(t *testing.T) { if _, err := os.Stat(filepath.Join(out, "py32f030x8.json")); !os.IsNotExist(err) { t.Fatalf("legacy target was generated: %v", err) } + checkFileContains(t, filepath.Join(out, "py32f002ax5.ld"), "_stack_size = 1K;") + checkFileContains(t, filepath.Join(out, "py32f030x8.ld"), "_stack_size = 2K;") + checkFileContains(t, filepath.Join(out, "py32l090xc.ld"), "_stack_size = 4K;") +} + +func checkFileContains(t *testing.T, path, want string) { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(data), want) { + t.Errorf("%s does not contain %q", path, want) + } } func checkBuildTags(t *testing.T, path string, want ...string) { From d7a1bda5957a6b7277b5763681092d01fea70274 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Wed, 26 Aug 2026 20:15:02 +0200 Subject: [PATCH 49/62] machine/py32: keep clock state internal --- src/machine/machine_py32_clock.go | 14 ++++++-------- src/machine/machine_py32_pin_afrh.go | 13 +++---------- src/machine/machine_py32_pin_no_afrh.go | 13 +++---------- src/runtime/runtime_py32.go | 7 +++---- testdata/py32-clock/main.go | 13 ++++++++++--- tools/gen-py32-targets/README.md | 5 ++--- 6 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index 30c87f569e..6f8c7da65f 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,14 +2,12 @@ package machine -// CPUFrequencyHz is the current CPU frequency in hertz. -// -// Application code that changes the system clock through the RCC registers -// must update this value after the new clock is stable, then reconfigure -// SysTick and any peripherals derived from the system clock. Assigning this -// variable does not configure the clock hardware. -var CPUFrequencyHz uint32 = defaultCPUFrequencyHz +var cpuFrequencyHz uint32 = defaultCPUFrequencyHz func CPUFrequency() uint32 { - return CPUFrequencyHz + return cpuFrequencyHz +} + +func setCPUFrequency(frequency uint32) { + cpuFrequencyHz = frequency } diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 9c0fdd5e1a..8ed466deb9 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -4,16 +4,9 @@ package machine import "device/py32" -// SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. -// -// Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a -// 4-bit field in the GPIO alternate-function registers. The register is split -// in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for -// pins 8–15, with each selector at bit offset (pin%8)*4 within its register. -// -// Alternate-function mappings vary by pin and PY32 variant; consult the -// device datasheet for the AF0-AF15 mapping. The pin must also be configured -// as PinAlternate via Pin.Configure before the alternate function takes effect. +// SetAltFunc selects a pin-specific alternate function. +// Configure the pin as PinAlternate first; AF values are listed in the device +// datasheet and vary by pin and device. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() if pin >= 8 { diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index 6a3368fe8c..dff488518a 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -4,16 +4,9 @@ package machine import "device/py32" -// SetAltFunc selects the alternate function for a GPIO pin on PY32F devices. -// -// Each pin supports up to 16 alternate functions (AF0–AF15), encoded as a -// 4-bit field in the GPIO alternate-function registers. The register is split -// in two: AFRL holds the 4-bit selectors for pins 0–7 and AFRH holds them for -// pins 8–15, with each selector at bit offset (pin%8)*4 within its register. -// -// Alternate-function mappings vary by pin and PY32 variant; consult the -// device datasheet for the AF0-AF15 mapping. The pin must also be configured -// as PinAlternate via Pin.Configure before the alternate function takes effect. +// SetAltFunc selects a pin-specific alternate function. +// Configure the pin as PinAlternate first; AF values are listed in the device +// datasheet and vary by pin and device. func (p Pin) SetAltFunc(af uint8) { port, pin := p.getPort() port.AFRL.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4) diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index 610e7a4a1e..d9b34b7c8d 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -17,16 +17,15 @@ func main() { configureHSI() - ConfigureSystemTimer() + configureSystemTimer() machine.InitSerial() run() exit(0) } -// Configure SysTick to fire every 1ms on given system frequency. -// This should be called after any change to the system clock frequency. -func ConfigureSystemTimer() { +// configureSystemTimer configures SysTick for 1ms ticks. +func configureSystemTimer() { arm.SetupSystemTimer(machine.CPUFrequency() / 1000) } diff --git a/testdata/py32-clock/main.go b/testdata/py32-clock/main.go index aaa4db950c..8d1913e910 100644 --- a/testdata/py32-clock/main.go +++ b/testdata/py32-clock/main.go @@ -1,18 +1,25 @@ package main import ( + "device/arm" "machine" - "runtime" "runtime/interrupt" + _ "unsafe" ) +//go:linkname setCPUFrequency machine.setCPUFrequency +func setCPUFrequency(frequency uint32) + // The application must establish and stabilize the hardware clock before // calling clockChanged. func clockChanged(frequency uint32, uartConfig machine.UARTConfig) error { state := interrupt.Disable() - machine.CPUFrequencyHz = frequency - runtime.ConfigureSystemTimer() + setCPUFrequency(frequency) + if err := arm.SetupSystemTimer(frequency / 1000); err != nil { + interrupt.Restore(state) + return err + } err := machine.DefaultUART.Configure(uartConfig) interrupt.Restore(state) return err diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index 0a9c7df3bd..e2ef02f812 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -57,6 +57,5 @@ serial interrupts, so its default USART is configured without receive interrupts rather than assigning an unverified IRQ number. The M4 SVDs also do not expose the M0+ `ICSCR.HSI_FS` selector, so the runtime preserves their reset clock configuration and initially reports the vendor-defined 8 MHz reset -frequency. Applications that establish a different clock tree must update -`machine.CPUFrequencyHz`, then reconfigure SysTick and frequency-dependent -peripherals. \ No newline at end of file +frequency. Custom clock HALs must update TinyGo's internal clock state, then +reconfigure SysTick and frequency-dependent peripherals. \ No newline at end of file From dbab89b034cfecdb360dea4893e3da6b7da112b7 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 15:59:10 +0200 Subject: [PATCH 50/62] targets/py32: normalize generated metadata --- src/machine/machine_py32_pin_afrh.go | 2 +- src/machine/machine_py32_pin_no_afrh.go | 2 +- .../machine_py32_uart_no_default_pins.go | 2 +- targets/embedfire-py32f002b.json | 4 +- targets/embedfire-py32f030.json | 4 +- targets/py32-m4.json | 1 + targets/py32.json | 3 +- targets/py32f001cxx.json | 2 +- targets/py32f002ax5.json | 8 +--- targets/py32f002bx5.json | 8 +--- targets/py32f002bxx.json | 2 +- targets/py32f002cxx.json | 2 +- targets/py32f002xxx.json | 2 +- targets/py32f002zxx.json | 2 +- targets/py32f003.json | 11 ----- targets/py32f003x4.json | 2 +- targets/py32f003x6.json | 2 +- targets/py32f003x7.json | 2 +- targets/py32f003x8.json | 2 +- targets/py32f030.json | 12 ----- targets/py32f030x4.json | 2 +- targets/py32f030x6.json | 2 +- targets/py32f030x7.json | 2 +- targets/py32f030x8.json | 4 +- targets/py32l020xx.json | 2 +- targets/py32m010xx.json | 2 +- tools/gen-py32-targets/README.md | 12 +++-- tools/gen-py32-targets/main.go | 45 +++++++++---------- tools/gen-py32-targets/main_test.go | 24 +++++----- 29 files changed, 69 insertions(+), 101 deletions(-) delete mode 100644 targets/py32f003.json delete mode 100644 targets/py32f030.json diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go index 8ed466deb9..41a3571f77 100644 --- a/src/machine/machine_py32_pin_afrh.go +++ b/src/machine/machine_py32_pin_afrh.go @@ -1,4 +1,4 @@ -//go:build py32 && !no_gpio_afrh +//go:build py32 && !py32_no_gpio_afrh package machine diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go index dff488518a..973e4c8b56 100644 --- a/src/machine/machine_py32_pin_no_afrh.go +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -1,4 +1,4 @@ -//go:build py32 && no_gpio_afrh +//go:build py32 && py32_no_gpio_afrh package machine diff --git a/src/machine/machine_py32_uart_no_default_pins.go b/src/machine/machine_py32_uart_no_default_pins.go index 8d7ed8387d..6ca8735b30 100644 --- a/src/machine/machine_py32_uart_no_default_pins.go +++ b/src/machine/machine_py32_uart_no_default_pins.go @@ -1,4 +1,4 @@ -//go:build py32 && !default_uart_pins +//go:build py32 && !py32_default_uart_pins package machine diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json index a58884aabe..0d071ab514 100644 --- a/targets/embedfire-py32f002b.json +++ b/targets/embedfire-py32f002b.json @@ -4,6 +4,6 @@ ], "build-tags": [ "embedfire_py32f002b", - "default_uart_pins" + "py32_default_uart_pins" ] -} \ No newline at end of file +} diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json index 1a636819cb..86e096fde1 100644 --- a/targets/embedfire-py32f030.json +++ b/targets/embedfire-py32f030.json @@ -4,6 +4,6 @@ ], "build-tags": [ "embedfire_py32f030", - "default_uart_pins" + "py32_default_uart_pins" ] -} \ No newline at end of file +} diff --git a/targets/py32-m4.json b/targets/py32-m4.json index 1ec16f63ec..da18a2e482 100644 --- a/targets/py32-m4.json +++ b/targets/py32-m4.json @@ -4,6 +4,7 @@ ], "scheduler": "none", "gc": "none", + "serial": "uart", "build-tags": [ "py32" ] diff --git a/targets/py32.json b/targets/py32.json index 6424ef633a..3acc4d2981 100644 --- a/targets/py32.json +++ b/targets/py32.json @@ -4,7 +4,8 @@ ], "scheduler": "none", "gc": "none", + "serial": "uart", "build-tags": [ "py32" ] -} \ No newline at end of file +} diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json index f73e021a97..01df490163 100644 --- a/targets/py32f001cxx.json +++ b/targets/py32f001cxx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f001cxx", - "no_gpio_afrh", + "py32_no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal" ], diff --git a/targets/py32f002ax5.json b/targets/py32f002ax5.json index b385ac3428..c2ab2878b6 100644 --- a/targets/py32f002ax5.json +++ b/targets/py32f002ax5.json @@ -1,14 +1,10 @@ { "inherits": [ - "py32" + "py32f002axx" ], "build-tags": [ - "py32f002axx", - "no_gpio_afrh" + "py32f002ax5" ], "linkerscript": "targets/py32f002ax5.ld", - "extra-files": [ - "src/device/py32/py32f002axx.s" - ], "flash-command": "pyocd load -t py32f002ax5 {bin}" } diff --git a/targets/py32f002bx5.json b/targets/py32f002bx5.json index 9f5355754d..16b267b2da 100644 --- a/targets/py32f002bx5.json +++ b/targets/py32f002bx5.json @@ -1,14 +1,10 @@ { "inherits": [ - "py32" + "py32f002bxx" ], "build-tags": [ - "py32f002bxx", - "no_gpio_afrh" + "py32f002bx5" ], "linkerscript": "targets/py32f002bx5.ld", - "extra-files": [ - "src/device/py32/py32f002bxx.s" - ], "flash-command": "pyocd load -t py32f002bx5 {bin}" } diff --git a/targets/py32f002bxx.json b/targets/py32f002bxx.json index 3181a623ad..b6f5ee532c 100644 --- a/targets/py32f002bxx.json +++ b/targets/py32f002bxx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f002bxx", - "no_gpio_afrh" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32f002bxx.s" diff --git a/targets/py32f002cxx.json b/targets/py32f002cxx.json index fb83d0afee..218270e8c6 100644 --- a/targets/py32f002cxx.json +++ b/targets/py32f002cxx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f002cxx", - "no_gpio_afrh", + "py32_no_gpio_afrh", "py32_hsi_fs_literal4" ], "extra-files": [ diff --git a/targets/py32f002xxx.json b/targets/py32f002xxx.json index 7f42ffa83b..c154530c4d 100644 --- a/targets/py32f002xxx.json +++ b/targets/py32f002xxx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f002xxx", - "no_gpio_afrh" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32f002xxx.s" diff --git a/targets/py32f002zxx.json b/targets/py32f002zxx.json index a436cc5cc8..4309cededd 100644 --- a/targets/py32f002zxx.json +++ b/targets/py32f002zxx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32f002zxx", - "no_gpio_afrh" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32f002zxx.s" diff --git a/targets/py32f003.json b/targets/py32f003.json deleted file mode 100644 index 1e8aaca9d2..0000000000 --- a/targets/py32f003.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "inherits": [ - "py32" - ], - "build-tags": [ - "py32f003xx" - ], - "extra-files": [ - "src/device/py32/py32f003xx.s" - ] -} diff --git a/targets/py32f003x4.json b/targets/py32f003x4.json index 0a6a7ca207..0abd943754 100644 --- a/targets/py32f003x4.json +++ b/targets/py32f003x4.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f003" + "py32f003xx" ], "build-tags": [ "py32f003x4" diff --git a/targets/py32f003x6.json b/targets/py32f003x6.json index 2081664535..a077dfcb89 100644 --- a/targets/py32f003x6.json +++ b/targets/py32f003x6.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f003" + "py32f003xx" ], "build-tags": [ "py32f003x6" diff --git a/targets/py32f003x7.json b/targets/py32f003x7.json index 4184c47f65..b92f567479 100644 --- a/targets/py32f003x7.json +++ b/targets/py32f003x7.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f003" + "py32f003xx" ], "build-tags": [ "py32f003x7" diff --git a/targets/py32f003x8.json b/targets/py32f003x8.json index fbd21f80b6..dbba064c80 100644 --- a/targets/py32f003x8.json +++ b/targets/py32f003x8.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f003" + "py32f003xx" ], "build-tags": [ "py32f003x8" diff --git a/targets/py32f030.json b/targets/py32f030.json deleted file mode 100644 index 93f28e0277..0000000000 --- a/targets/py32f030.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "inherits": [ - "py32" - ], - "build-tags": [ - "py32f030", - "py32f030xx" - ], - "extra-files": [ - "src/device/py32/py32f030xx.s" - ] -} \ No newline at end of file diff --git a/targets/py32f030x4.json b/targets/py32f030x4.json index 8da7c34b2c..e1332d6390 100644 --- a/targets/py32f030x4.json +++ b/targets/py32f030x4.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f030" + "py32f030xx" ], "build-tags": [ "py32f030x4" diff --git a/targets/py32f030x6.json b/targets/py32f030x6.json index 27b3e0849c..58d419ce4d 100644 --- a/targets/py32f030x6.json +++ b/targets/py32f030x6.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f030" + "py32f030xx" ], "build-tags": [ "py32f030x6" diff --git a/targets/py32f030x7.json b/targets/py32f030x7.json index 7d611efbb4..61e704065d 100644 --- a/targets/py32f030x7.json +++ b/targets/py32f030x7.json @@ -1,6 +1,6 @@ { "inherits": [ - "py32f030" + "py32f030xx" ], "build-tags": [ "py32f030x7" diff --git a/targets/py32f030x8.json b/targets/py32f030x8.json index f4e992b73d..440decefba 100644 --- a/targets/py32f030x8.json +++ b/targets/py32f030x8.json @@ -1,10 +1,10 @@ { "inherits": [ - "py32f030" + "py32f030xx" ], "build-tags": [ "py32f030x8" ], "linkerscript": "targets/py32f030x8.ld", "flash-command": "pyocd load -t py32f030x8 {bin}" -} \ No newline at end of file +} diff --git a/targets/py32l020xx.json b/targets/py32l020xx.json index 0e6b2eb55f..2f29798986 100644 --- a/targets/py32l020xx.json +++ b/targets/py32l020xx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32l020xx", - "no_gpio_afrh" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32l020xx.s" diff --git a/targets/py32m010xx.json b/targets/py32m010xx.json index 7947f476a4..9d604615e8 100644 --- a/targets/py32m010xx.json +++ b/targets/py32m010xx.json @@ -4,7 +4,7 @@ ], "build-tags": [ "py32m010xx", - "no_gpio_afrh" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32m010xx.s" diff --git a/tools/gen-py32-targets/README.md b/tools/gen-py32-targets/README.md index e2ef02f812..9c4f099d00 100644 --- a/tools/gen-py32-targets/README.md +++ b/tools/gen-py32-targets/README.md @@ -20,7 +20,7 @@ Together these inputs produce family targets for all 41 available SVDs. Cortex-M0+ families inherit `py32`; PY32E407, PY32F403, and PY32F410 families inherit `py32-m4`, which uses TinyGo's standard soft-float Cortex-M4 ABI. Targets -whose SVD has no `GPIO.AFRH` register receive the `no_gpio_afrh` build tag. +whose SVD has no `GPIO.AFRH` register receive the `py32_no_gpio_afrh` build tag. Puya's SVDs are inconsistent about GPIO `groupName`: some describe identical ports as `GPIOA_Type`, `GPIOB_Type`, and so on, while others use one @@ -35,12 +35,10 @@ registers, `USART` versus `UART` blocks, split USART receive/transmit data registers, and HSI selector availability. Keep these classifications in the target generator rather than adding long family expressions to machine files. -Existing PY32 target JSON files are retained for compatibility. In particular, -their established aliases and flashing commands are not regenerated. Linker -scripts are generated for every concrete target so memory definitions and stack -sizes remain consistent. Newly generated targets intentionally omit flashing -commands because a compatible programmer identifier has not been verified for -every Puya part. +All concrete target JSON files and linker scripts are generated so inheritance, +memory definitions, and stack sizes remain consistent. Verified flashing +commands are preserved in the generator; other targets omit them until a +compatible programmer identifier is known. The system and interrupt stack is sized from available RAM: targets with up to 4 KiB use 1 KiB, targets with up to 16 KiB use 2 KiB, and larger targets use diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 412fea2ea7..4328d5ac2f 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -31,6 +31,7 @@ type target struct { BuildTags []string `json:"build-tags,omitempty"` LinkerScript string `json:"linkerscript,omitempty"` ExtraFiles []string `json:"extra-files,omitempty"` + FlashCommand string `json:"flash-command,omitempty"` } var orphanFamilies = map[string]string{ @@ -77,7 +78,7 @@ func familyBuildTags(family string) []string { name string set map[string]bool }{ - {"no_gpio_afrh", noGPIOAFRH}, + {"py32_no_gpio_afrh", noGPIOAFRH}, {"py32_gpio_ospdder", gpioOSPDDER}, {"py32_gpio_clock_ahb2", gpioClockAHB2}, {"py32_gpio_clock_ahb", gpioClockAHB}, @@ -100,20 +101,17 @@ func familyBuildTags(family string) []string { return tags } -var legacyTargetJSON = map[string]bool{ - // Keep pre-existing JSON definitions, including established aliases and - // flashing commands. Their linker scripts are still generated from the - // normalized device table. - "py32f002ax5": true, - "py32f002bx5": true, - "py32f003x4": true, - "py32f003x6": true, - "py32f003x7": true, - "py32f003x8": true, - "py32f030x4": true, - "py32f030x6": true, - "py32f030x7": true, - "py32f030x8": true, +var flashCommands = map[string]string{ + "py32f002ax5": "pyocd load -t py32f002ax5 {bin}", + "py32f002bx5": "pyocd load -t py32f002bx5 {bin}", + "py32f003x4": "pyocd load -t py32f003x4 {bin}", + "py32f003x6": "pyocd load -t py32f003x6 {bin}", + "py32f003x7": "pyocd load -t py32f003x7 {bin}", + "py32f003x8": "pyocd load -t py32f003x8 {bin}", + "py32f030x4": "pyocd load -t py32f030x4 {bin}", + "py32f030x6": "pyocd load -t py32f030x6 {bin}", + "py32f030x7": "pyocd load -t py32f030x7 {bin}", + "py32f030x8": "pyocd load -t py32f030x8 {bin}", } func main() { @@ -232,15 +230,14 @@ func generate(out string, devices []device) error { } for _, device := range devices { - if !legacyTargetJSON[device.Part] { - spec := target{ - Inherits: []string{device.Family}, - BuildTags: []string{device.Part}, - LinkerScript: "targets/" + device.Part + ".ld", - } - if err := writeJSON(filepath.Join(out, device.Part+".json"), spec); err != nil { - return err - } + spec := target{ + Inherits: []string{device.Family}, + BuildTags: []string{device.Part}, + LinkerScript: "targets/" + device.Part + ".ld", + FlashCommand: flashCommands[device.Part], + } + if err := writeJSON(filepath.Join(out, device.Part+".json"), spec); err != nil { + return err } stackSize := systemStackSize(device.RAMSize) linker := fmt.Sprintf("MEMORY\n{\n FLASH_TEXT (rx) : ORIGIN = %#x, LENGTH = %#x\n RAM (xrw) : ORIGIN = %#x, LENGTH = %#x\n}\n\n_stack_size = %dK;\n\nINCLUDE \"targets/arm.ld\"\n", device.FlashStart, device.FlashSize, device.RAMStart, device.RAMSize, stackSize/1024) diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index 760133fb40..ac5ff97988 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -69,18 +69,20 @@ func TestGenerate(t *testing.T) { if err != nil { t.Fatal(err) } - // 41 family JSON files, 77 generated concrete JSON files, and linker + // 41 family JSON files, 87 generated concrete JSON files, and linker // scripts for all 87 concrete targets. - if got, want := len(entries), 205; got != want { + if got, want := len(entries), 215; got != want { t.Fatalf("generated %d files, want %d", got, want) } - checkTarget(t, filepath.Join(out, "py32e407xc.json"), "py32e407xx", "targets/py32e407xc.ld") - checkTarget(t, filepath.Join(out, "py32f001xx.json"), "py32", "") - checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "") + checkTarget(t, filepath.Join(out, "py32e407xc.json"), "py32e407xx", "targets/py32e407xc.ld", "") + checkTarget(t, filepath.Join(out, "py32f001xx.json"), "py32", "", "") + checkTarget(t, filepath.Join(out, "py32f002ax5.json"), "py32f002axx", "targets/py32f002ax5.ld", "pyocd load -t py32f002ax5 {bin}") + checkTarget(t, filepath.Join(out, "py32f030x8.json"), "py32f030xx", "targets/py32f030x8.ld", "pyocd load -t py32f030x8 {bin}") + checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") - checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") - checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "no_gpio_afrh", "py32_hsi_fs_literal4") + checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") + checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") @@ -93,9 +95,6 @@ func TestGenerate(t *testing.T) { if !contains(string(data), want) { t.Fatalf("E407 linker script does not contain combined contiguous RAM %q", want) } - if _, err := os.Stat(filepath.Join(out, "py32f030x8.json")); !os.IsNotExist(err) { - t.Fatalf("legacy target was generated: %v", err) - } checkFileContains(t, filepath.Join(out, "py32f002ax5.ld"), "_stack_size = 1K;") checkFileContains(t, filepath.Join(out, "py32f030x8.ld"), "_stack_size = 2K;") checkFileContains(t, filepath.Join(out, "py32l090xc.ld"), "_stack_size = 4K;") @@ -127,7 +126,7 @@ func checkBuildTags(t *testing.T, path string, want ...string) { } } -func checkTarget(t *testing.T, path, inherited, linker string) { +func checkTarget(t *testing.T, path, inherited, linker, flashCommand string) { t.Helper() data, err := os.ReadFile(path) if err != nil { @@ -143,6 +142,9 @@ func checkTarget(t *testing.T, path, inherited, linker string) { if spec.LinkerScript != linker { t.Errorf("%s linker script is %q, want %q", path, spec.LinkerScript, linker) } + if spec.FlashCommand != flashCommand { + t.Errorf("%s flash command is %q, want %q", path, spec.FlashCommand, flashCommand) + } } func contains(value, substring string) bool { From 5fb9fcea66c679f9f9f7f9324d17e438bf12cb92 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 16:02:00 +0200 Subject: [PATCH 51/62] machine/py32: normalize GPIO configuration --- src/machine/machine_py32_pin.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go index 284f2963ff..ea9cd99206 100644 --- a/src/machine/machine_py32_pin.go +++ b/src/machine/machine_py32_pin.go @@ -137,13 +137,12 @@ const ( const ( PinOutput PinMode = iota - PinInputFloating + PinInput PinInputPulldown PinInputPullup PinInputAnalog PinAlternate ) -const PinInput PinMode = PinInputFloating // These unshifted encodings are shared by the supported PY32 parts. Register // masks come from the generated device definitions. @@ -198,11 +197,11 @@ func (p Pin) Get() bool { func (p Pin) Configure(config PinConfig) { p.enableClock() port, pin := p.getPort() - pos := (pin % 16) * 2 + pos := pin * 2 switch config.Mode { - case PinInputFloating: + case PinInput: port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) case PinInputPulldown: @@ -220,6 +219,8 @@ func (p Pin) Configure(config PinConfig) { port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) case PinAlternate: port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + port.OTYPER.ReplaceBits(gpioOutputTypePushPull, gpioOutputTypeMask, pos>>1) setPinOutputSpeed(port, gpioOutputSpeedHigh, pos) } } From fdfcbe9044cb536d2782a7365bfbc5c02132b26f Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 16:05:52 +0200 Subject: [PATCH 52/62] machine/py32: fix T020 UART setup --- src/machine/machine_py32_uart_type.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go index f4a520373c..97ce20fd8a 100644 --- a/src/machine/machine_py32_uart_type.go +++ b/src/machine/machine_py32_uart_type.go @@ -27,10 +27,11 @@ func (uart *UART) Configure(config UARTConfig) error { } py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_UART1EN) - uart.Bus.CR1.Set(0) + uart.Bus.CR1.Set(py32.UART_CR1_M_Msk) uart.Bus.CR2.Set(py32.UART_CR2_RXNEIE) uart.Bus.CR3.Set(0) - uart.Bus.BRR.Set((CPUFrequency() + config.BaudRate/2) / config.BaudRate) + divider := (CPUFrequency() + config.BaudRate*8) / (config.BaudRate * 16) + uart.Bus.BRR.Set(divider) uart.irq = interrupt.New(py32.IRQ_UART1, handleUART1Interrupt) uart.irq.SetPriority(0xc0) @@ -44,7 +45,7 @@ func handleUART1Interrupt(interrupt.Interrupt) { func (uart *UART) writeByte(c byte) error { retries := uart.txRetries - for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 { + for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TDRE == 0 { uartYield() retries-- } From aa5d05d2a3822e5155b6a626ae7143066f7a1db0 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 16:12:11 +0200 Subject: [PATCH 53/62] machine/py32: reduce clock variant files --- src/machine/machine_py32_clock.go | 11 ++++++++++- src/machine/machine_py32_clock_24mhz.go | 5 ----- src/machine/machine_py32_clock_8mhz.go | 5 ----- src/machine/machine_py32_uart_clock.go | 4 ++-- src/machine/machine_py32_uart_clock_apb2.go | 2 +- src/machine/machine_py32_uart_clock_literal.go | 11 ----------- src/runtime/runtime_py32_hsi_literal3.go | 4 +--- src/runtime/runtime_py32_hsi_literal4.go | 4 +--- targets/py32e407xx.json | 3 +-- targets/py32f001cxx.json | 3 +-- targets/py32f001xx.json | 3 +-- targets/py32f403xx.json | 3 +-- targets/py32f410xx.json | 1 - tools/gen-py32-targets/main.go | 4 ---- tools/gen-py32-targets/main_test.go | 6 +++--- 15 files changed, 22 insertions(+), 47 deletions(-) delete mode 100644 src/machine/machine_py32_clock_24mhz.go delete mode 100644 src/machine/machine_py32_clock_8mhz.go delete mode 100644 src/machine/machine_py32_uart_clock_literal.go diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index 6f8c7da65f..738672382f 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,7 +2,16 @@ package machine -var cpuFrequencyHz uint32 = defaultCPUFrequencyHz +import "device/py32" + +var cpuFrequencyHz = initialCPUFrequency() + +func initialCPUFrequency() uint32 { + if py32.CPU == "CM4" { + return 8_000_000 + } + return 24_000_000 +} func CPUFrequency() uint32 { return cpuFrequencyHz diff --git a/src/machine/machine_py32_clock_24mhz.go b/src/machine/machine_py32_clock_24mhz.go deleted file mode 100644 index a1e8a072de..0000000000 --- a/src/machine/machine_py32_clock_24mhz.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build py32 && !py32_no_hsi_fs - -package machine - -const defaultCPUFrequencyHz = 24_000_000 diff --git a/src/machine/machine_py32_clock_8mhz.go b/src/machine/machine_py32_clock_8mhz.go deleted file mode 100644 index 554e9fca8a..0000000000 --- a/src/machine/machine_py32_clock_8mhz.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build py32 && py32_no_hsi_fs - -package machine - -const defaultCPUFrequencyHz = 8_000_000 diff --git a/src/machine/machine_py32_uart_clock.go b/src/machine/machine_py32_uart_clock.go index 3f066a2bd7..fc6164e67a 100644 --- a/src/machine/machine_py32_uart_clock.go +++ b/src/machine/machine_py32_uart_clock.go @@ -1,9 +1,9 @@ -//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && !py32_usart1_clock_literal +//go:build py32 && !py32_uart_type && !py32_no_hsi_fs package machine import "device/py32" func enableUSART1Clock() { - py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) + py32.RCC.APBENR2.SetBits(1 << 14) } diff --git a/src/machine/machine_py32_uart_clock_apb2.go b/src/machine/machine_py32_uart_clock_apb2.go index 4eeb94429a..ae1e4c1d12 100644 --- a/src/machine/machine_py32_uart_clock_apb2.go +++ b/src/machine/machine_py32_uart_clock_apb2.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_uart_type && py32_uart_clock_apb2 +//go:build py32 && !py32_uart_type && py32_no_hsi_fs package machine diff --git a/src/machine/machine_py32_uart_clock_literal.go b/src/machine/machine_py32_uart_clock_literal.go deleted file mode 100644 index d4352f7510..0000000000 --- a/src/machine/machine_py32_uart_clock_literal.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && py32_usart1_clock_literal - -package machine - -import "device/py32" - -func enableUSART1Clock() { - // The F001 pack omits its referenced device header, and its SVD omits the - // APBENR2 USART1EN field. The vendor system layout places it at bit 14. - py32.RCC.APBENR2.SetBits(1 << 14) -} diff --git a/src/runtime/runtime_py32_hsi_literal3.go b/src/runtime/runtime_py32_hsi_literal3.go index 0d574e8f0e..b6ebb7bdca 100644 --- a/src/runtime/runtime_py32_hsi_literal3.go +++ b/src/runtime/runtime_py32_hsi_literal3.go @@ -4,9 +4,7 @@ package runtime import "device/py32" -// The F032 header names this field HSI_FS_CR while its SVD names it HSI_FS, so -// no matching header-derived value constants are generated. Puya's official -// system source maps encoding 3 to 24 MHz. +// The F032 header does not provide value constants for this field. func configureHSI() { py32.RCC.SetICSCR_HSI_FS(3) } diff --git a/src/runtime/runtime_py32_hsi_literal4.go b/src/runtime/runtime_py32_hsi_literal4.go index 0b7c9b8390..0fe55f8f23 100644 --- a/src/runtime/runtime_py32_hsi_literal4.go +++ b/src/runtime/runtime_py32_hsi_literal4.go @@ -4,9 +4,7 @@ package runtime import "device/py32" -// F001 lacks its referenced device header. F002C's header shifts its HSI_FS -// bits by the unrelated LSI_TRIM position. In both cases Puya's official system -// sources map encoding 4 to the runtime's 24 MHz clock. +// The affected vendor headers do not provide usable value constants. func configureHSI() { py32.RCC.SetICSCR_HSI_FS(4) } diff --git a/targets/py32e407xx.json b/targets/py32e407xx.json index dabb31491b..4be29efeb2 100644 --- a/targets/py32e407xx.json +++ b/targets/py32e407xx.json @@ -7,8 +7,7 @@ "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", - "py32_usart_split_data", - "py32_uart_clock_apb2" + "py32_usart_split_data" ], "extra-files": [ "src/device/py32/py32e407xx.s" diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json index 01df490163..ace8c0caaa 100644 --- a/targets/py32f001cxx.json +++ b/targets/py32f001cxx.json @@ -5,8 +5,7 @@ "build-tags": [ "py32f001cxx", "py32_no_gpio_afrh", - "py32_hsi_fs_literal4", - "py32_usart1_clock_literal" + "py32_hsi_fs_literal4" ], "extra-files": [ "src/device/py32/py32f001cxx.s" diff --git a/targets/py32f001xx.json b/targets/py32f001xx.json index 9fedf12b9a..242a6c4f80 100644 --- a/targets/py32f001xx.json +++ b/targets/py32f001xx.json @@ -4,8 +4,7 @@ ], "build-tags": [ "py32f001xx", - "py32_hsi_fs_literal4", - "py32_usart1_clock_literal" + "py32_hsi_fs_literal4" ], "extra-files": [ "src/device/py32/py32f001xx.s" diff --git a/targets/py32f403xx.json b/targets/py32f403xx.json index 1afdd3eaf6..bd0727e9b9 100644 --- a/targets/py32f403xx.json +++ b/targets/py32f403xx.json @@ -5,8 +5,7 @@ "build-tags": [ "py32f403xx", "py32_gpio_clock_ahb2", - "py32_no_hsi_fs", - "py32_uart_clock_apb2" + "py32_no_hsi_fs" ], "extra-files": [ "src/device/py32/py32f403xx.s" diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json index 154465b63e..44949c9a8f 100644 --- a/targets/py32f410xx.json +++ b/targets/py32f410xx.json @@ -8,7 +8,6 @@ "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", - "py32_uart_clock_apb2", "py32_uart_no_interrupt" ], "extra-files": [ diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 4328d5ac2f..a2ab8fcb64 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -60,8 +60,6 @@ var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") var usartUnnumbered = familySet("py32f410xx") -var usart1ClockLiteral = familySet("py32f001cxx", "py32f001xx") -var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartNoInterrupt = familySet("py32f410xx") func familySet(names ...string) map[string]bool { @@ -89,8 +87,6 @@ func familyBuildTags(family string) []string { {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, {"py32_usart_unnumbered", usartUnnumbered}, - {"py32_usart1_clock_literal", usart1ClockLiteral}, - {"py32_uart_clock_apb2", uartClockAPB2}, {"py32_uart_no_interrupt", uartNoInterrupt}, } for _, feature := range features { diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index ac5ff97988..a699a1ca46 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -80,11 +80,11 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32f002ax5.json"), "py32f002axx", "targets/py32f002ax5.ld", "pyocd load -t py32f002ax5 {bin}") checkTarget(t, filepath.Join(out, "py32f030x8.json"), "py32f030xx", "targets/py32f030x8.ld", "pyocd load -t py32f030x8 {bin}") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") - checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") - checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") + checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data") + checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") - checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") + checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) From 189ed929386ae845e2121e7e3c41ccf2e906b0f0 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 16:13:29 +0200 Subject: [PATCH 54/62] machine/py32: clean up UART variants --- src/machine/machine_py32_uart2.go | 4 ++-- src/machine/machine_py32_uart_common.go | 6 +++--- src/runtime/runtime_py32.go | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/machine/machine_py32_uart2.go b/src/machine/machine_py32_uart2.go index 1ffe196dfe..388f8399c5 100644 --- a/src/machine/machine_py32_uart2.go +++ b/src/machine/machine_py32_uart2.go @@ -1,4 +1,4 @@ -//go:build py32f003xx || py32f030xx || py32f040xx +//go:build py32 && (py32f003xx || py32f030xx || py32f040xx) package machine @@ -23,7 +23,7 @@ func setupUSART2(uart *UART) { } func handleUSART2Interrupt(interrupt.Interrupt) { - usart2RX.Receive(uint8(usart2RX.Bus.DR.Get())) + usart2RX.Receive(uint8(readUSARTData(usart2RX.Bus))) } // usart2RX is the UART serviced by handleUSART2Interrupt, set by setupUSART2. diff --git a/src/machine/machine_py32_uart_common.go b/src/machine/machine_py32_uart_common.go index 4429fd144e..461f020b92 100644 --- a/src/machine/machine_py32_uart_common.go +++ b/src/machine/machine_py32_uart_common.go @@ -4,14 +4,14 @@ package machine import "runtime/interrupt" -// errUARTWriteTimeout is returned by writeByte when the TX register does not -// become empty within the retry budget. type uartError string func (e uartError) Error() string { return string(e) } +// errUARTWriteTimeout is returned when the transmit register stays busy. +const errUARTWriteTimeout uartError = "UART: write timeout" + const ( - errUARTWriteTimeout uartError = "UART: write timeout" errUARTInvalidTXPin uartError = "UART: invalid TX pin" errUARTInvalidRXPin uartError = "UART: invalid RX pin" errUARTPinsEqual uartError = "UART: TX and RX pins must differ" diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go index d9b34b7c8d..d796f4e374 100644 --- a/src/runtime/runtime_py32.go +++ b/src/runtime/runtime_py32.go @@ -5,7 +5,6 @@ package runtime import ( "device/arm" "machine" - "runtime/volatile" ) @@ -29,8 +28,8 @@ func configureSystemTimer() { arm.SetupSystemTimer(machine.CPUFrequency() / 1000) } -func ticksToNanoseconds(ticks timeUnit) int64 { - return int64(ticks * 1000_000) +func ticksToNanoseconds(value timeUnit) int64 { + return int64(value * 1000_000) } func nanosecondsToTicks(ns int64) timeUnit { From 06a523e0e65daba8be3b21a07f392401a8b93e02 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 16:20:49 +0200 Subject: [PATCH 55/62] machine/py32: decouple UART clock capability --- src/machine/machine_py32_uart_clock.go | 2 +- src/machine/machine_py32_uart_clock_apb2.go | 2 +- targets/py32e407xx.json | 3 ++- targets/py32f403xx.json | 3 ++- targets/py32f410xx.json | 1 + tools/gen-py32-targets/main.go | 2 ++ tools/gen-py32-targets/main_test.go | 4 ++-- 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/machine/machine_py32_uart_clock.go b/src/machine/machine_py32_uart_clock.go index fc6164e67a..914a662bee 100644 --- a/src/machine/machine_py32_uart_clock.go +++ b/src/machine/machine_py32_uart_clock.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_uart_type && !py32_no_hsi_fs +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 package machine diff --git a/src/machine/machine_py32_uart_clock_apb2.go b/src/machine/machine_py32_uart_clock_apb2.go index ae1e4c1d12..4eeb94429a 100644 --- a/src/machine/machine_py32_uart_clock_apb2.go +++ b/src/machine/machine_py32_uart_clock_apb2.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_uart_type && py32_no_hsi_fs +//go:build py32 && !py32_uart_type && py32_uart_clock_apb2 package machine diff --git a/targets/py32e407xx.json b/targets/py32e407xx.json index 4be29efeb2..dabb31491b 100644 --- a/targets/py32e407xx.json +++ b/targets/py32e407xx.json @@ -7,7 +7,8 @@ "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", - "py32_usart_split_data" + "py32_usart_split_data", + "py32_uart_clock_apb2" ], "extra-files": [ "src/device/py32/py32e407xx.s" diff --git a/targets/py32f403xx.json b/targets/py32f403xx.json index bd0727e9b9..1afdd3eaf6 100644 --- a/targets/py32f403xx.json +++ b/targets/py32f403xx.json @@ -5,7 +5,8 @@ "build-tags": [ "py32f403xx", "py32_gpio_clock_ahb2", - "py32_no_hsi_fs" + "py32_no_hsi_fs", + "py32_uart_clock_apb2" ], "extra-files": [ "src/device/py32/py32f403xx.s" diff --git a/targets/py32f410xx.json b/targets/py32f410xx.json index 44949c9a8f..154465b63e 100644 --- a/targets/py32f410xx.json +++ b/targets/py32f410xx.json @@ -8,6 +8,7 @@ "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", + "py32_uart_clock_apb2", "py32_uart_no_interrupt" ], "extra-files": [ diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index a2ab8fcb64..82a98a4690 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -60,6 +60,7 @@ var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") var usartUnnumbered = familySet("py32f410xx") +var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartNoInterrupt = familySet("py32f410xx") func familySet(names ...string) map[string]bool { @@ -87,6 +88,7 @@ func familyBuildTags(family string) []string { {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, {"py32_usart_unnumbered", usartUnnumbered}, + {"py32_uart_clock_apb2", uartClockAPB2}, {"py32_uart_no_interrupt", uartNoInterrupt}, } for _, feature := range features { diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index a699a1ca46..dd32c78b59 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -80,11 +80,11 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32f002ax5.json"), "py32f002axx", "targets/py32f002ax5.ld", "pyocd load -t py32f002ax5 {bin}") checkTarget(t, filepath.Join(out, "py32f030x8.json"), "py32f030xx", "targets/py32f030x8.ld", "pyocd load -t py32f030x8 {bin}") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") - checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data") + checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") - checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_no_interrupt") + checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") data, err := os.ReadFile(filepath.Join(out, "py32e407xc.ld")) From f6212fc58989b3721c12a14bbee27d4d818eae12 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 18:08:00 +0200 Subject: [PATCH 56/62] lib/py32-svd: use organization repository --- .gitmodules | 2 +- make/gen-device.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8568346a95..44a0126ef2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,4 +43,4 @@ url = https://github.com/ivmai/bdwgc.git [submodule "lib/py32-svd"] path = lib/py32-svd - url = https://github.com/burgrp/py32-svd.git + url = https://github.com/tinygo-org/py32-svd.git diff --git a/make/gen-device.mk b/make/gen-device.mk index 135879385c..9f3c5cf972 100644 --- a/make/gen-device.mk +++ b/make/gen-device.mk @@ -60,7 +60,7 @@ gen-device-renesas: build/gen-device-svd GO111MODULE=off $(GO) fmt ./src/device/renesas gen-device-py32: build/gen-device-svd - ./build/gen-device-svd -source=https://github.com/burgrp/py32-svd lib/py32-svd/svd src/device/py32/ + ./build/gen-device-svd -source=https://github.com/tinygo-org/py32-svd lib/py32-svd/svd src/device/py32/ GO111MODULE=off $(GO) fmt ./src/device/py32 gen-target-py32: ## Generate PY32 target and linker definitions From 243201180f7a77c9b6a4cc509b9e72828fcda329 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 20:48:30 +0200 Subject: [PATCH 57/62] runtime/py32: name 24MHz HSI encodings --- lib/py32-svd | 2 +- src/runtime/runtime_py32_hsi.go | 4 ++-- src/runtime/runtime_py32_hsi_literal3.go | 10 ---------- targets/py32f001xx.json | 3 +-- targets/py32f032xx.json | 3 +-- tools/gen-py32-targets/main.go | 4 +--- tools/gen-py32-targets/main_test.go | 3 ++- 7 files changed, 8 insertions(+), 21 deletions(-) delete mode 100644 src/runtime/runtime_py32_hsi_literal3.go diff --git a/lib/py32-svd b/lib/py32-svd index 982b09364d..93af0a9a84 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit 982b09364d84bf829b172d3e43b14f81b325ad7d +Subproject commit 93af0a9a8481e0b3c8405fa77db18c5a1e1d7562 diff --git a/src/runtime/runtime_py32_hsi.go b/src/runtime/runtime_py32_hsi.go index 48eea04293..dd2d0bb42a 100644 --- a/src/runtime/runtime_py32_hsi.go +++ b/src/runtime/runtime_py32_hsi.go @@ -1,9 +1,9 @@ -//go:build py32 && !py32_hsi_fs_op && !py32_hsi_fs_literal3 && !py32_hsi_fs_literal4 && !py32_no_hsi_fs +//go:build py32 && !py32_hsi_fs_op && !py32_hsi_fs_literal4 && !py32_no_hsi_fs package runtime import "device/py32" func configureHSI() { - py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_2) + py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) } diff --git a/src/runtime/runtime_py32_hsi_literal3.go b/src/runtime/runtime_py32_hsi_literal3.go deleted file mode 100644 index b6ebb7bdca..0000000000 --- a/src/runtime/runtime_py32_hsi_literal3.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build py32 && py32_hsi_fs_literal3 - -package runtime - -import "device/py32" - -// The F032 header does not provide value constants for this field. -func configureHSI() { - py32.RCC.SetICSCR_HSI_FS(3) -} diff --git a/targets/py32f001xx.json b/targets/py32f001xx.json index 242a6c4f80..58248f3e1b 100644 --- a/targets/py32f001xx.json +++ b/targets/py32f001xx.json @@ -3,8 +3,7 @@ "py32" ], "build-tags": [ - "py32f001xx", - "py32_hsi_fs_literal4" + "py32f001xx" ], "extra-files": [ "src/device/py32/py32f001xx.s" diff --git a/targets/py32f032xx.json b/targets/py32f032xx.json index 4acca46023..be4cc0c5da 100644 --- a/targets/py32f032xx.json +++ b/targets/py32f032xx.json @@ -3,8 +3,7 @@ "py32" ], "build-tags": [ - "py32f032xx", - "py32_hsi_fs_literal3" + "py32f032xx" ], "extra-files": [ "src/device/py32/py32f032xx.s" diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 82a98a4690..37b73e2604 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -54,8 +54,7 @@ var gpioOSPDDER = familySet("py32e407xx", "py32f410xx", "py32l090xx", "py32t090x var gpioClockAHB2 = familySet("py32e407xx", "py32f403xx") var gpioClockAHB = familySet("py32f410xx") var hsiFSOP = familySet("py32l090xx", "py32t090xx", "py32t092xx") -var hsiFSLiteral3 = familySet("py32f032xx") -var hsiFSLiteral4 = familySet("py32f001cxx", "py32f001xx", "py32f002cxx") +var hsiFSLiteral4 = familySet("py32f001cxx", "py32f002cxx") var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") @@ -82,7 +81,6 @@ func familyBuildTags(family string) []string { {"py32_gpio_clock_ahb2", gpioClockAHB2}, {"py32_gpio_clock_ahb", gpioClockAHB}, {"py32_hsi_fs_op", hsiFSOP}, - {"py32_hsi_fs_literal3", hsiFSLiteral3}, {"py32_hsi_fs_literal4", hsiFSLiteral4}, {"py32_no_hsi_fs", noHSIFS}, {"py32_uart_type", uartType}, diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index dd32c78b59..5d59113be0 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -82,8 +82,9 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") + checkBuildTags(t, filepath.Join(out, "py32f001xx.json"), "py32f001xx") checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") - checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx", "py32_hsi_fs_literal3") + checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx") checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type") From 10228f6aec0ebfecec514388abdf57e3e988ba4f Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 20:49:58 +0200 Subject: [PATCH 58/62] machine/py32: derive startup clock from capability --- src/machine/machine_py32_clock.go | 11 +---------- src/machine/machine_py32_clock_24mhz.go | 5 +++++ src/machine/machine_py32_clock_8mhz.go | 5 +++++ 3 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 src/machine/machine_py32_clock_24mhz.go create mode 100644 src/machine/machine_py32_clock_8mhz.go diff --git a/src/machine/machine_py32_clock.go b/src/machine/machine_py32_clock.go index 738672382f..6f8c7da65f 100644 --- a/src/machine/machine_py32_clock.go +++ b/src/machine/machine_py32_clock.go @@ -2,16 +2,7 @@ package machine -import "device/py32" - -var cpuFrequencyHz = initialCPUFrequency() - -func initialCPUFrequency() uint32 { - if py32.CPU == "CM4" { - return 8_000_000 - } - return 24_000_000 -} +var cpuFrequencyHz uint32 = defaultCPUFrequencyHz func CPUFrequency() uint32 { return cpuFrequencyHz diff --git a/src/machine/machine_py32_clock_24mhz.go b/src/machine/machine_py32_clock_24mhz.go new file mode 100644 index 0000000000..a1e8a072de --- /dev/null +++ b/src/machine/machine_py32_clock_24mhz.go @@ -0,0 +1,5 @@ +//go:build py32 && !py32_no_hsi_fs + +package machine + +const defaultCPUFrequencyHz = 24_000_000 diff --git a/src/machine/machine_py32_clock_8mhz.go b/src/machine/machine_py32_clock_8mhz.go new file mode 100644 index 0000000000..554e9fca8a --- /dev/null +++ b/src/machine/machine_py32_clock_8mhz.go @@ -0,0 +1,5 @@ +//go:build py32 && py32_no_hsi_fs + +package machine + +const defaultCPUFrequencyHz = 8_000_000 From 381d45f61ef173c04ada750385b5a5dc971cb1ac Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 20:51:18 +0200 Subject: [PATCH 59/62] machine/py32: use generated USART clock mask --- src/machine/machine_py32_uart_clock.go | 4 ++-- src/machine/machine_py32_uart_clock_literal.go | 10 ++++++++++ targets/py32f001cxx.json | 3 ++- targets/py32f001xx.json | 3 ++- tools/gen-py32-targets/main.go | 2 ++ tools/gen-py32-targets/main_test.go | 4 ++-- 6 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 src/machine/machine_py32_uart_clock_literal.go diff --git a/src/machine/machine_py32_uart_clock.go b/src/machine/machine_py32_uart_clock.go index 914a662bee..3f066a2bd7 100644 --- a/src/machine/machine_py32_uart_clock.go +++ b/src/machine/machine_py32_uart_clock.go @@ -1,9 +1,9 @@ -//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && !py32_usart1_clock_literal package machine import "device/py32" func enableUSART1Clock() { - py32.RCC.APBENR2.SetBits(1 << 14) + py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) } diff --git a/src/machine/machine_py32_uart_clock_literal.go b/src/machine/machine_py32_uart_clock_literal.go new file mode 100644 index 0000000000..dd82965783 --- /dev/null +++ b/src/machine/machine_py32_uart_clock_literal.go @@ -0,0 +1,10 @@ +//go:build py32 && !py32_uart_type && !py32_uart_clock_apb2 && py32_usart1_clock_literal + +package machine + +import "device/py32" + +func enableUSART1Clock() { + // The F001 SVDs omit USART1EN; the vendor register layout places it at bit 14. + py32.RCC.APBENR2.SetBits(1 << 14) +} diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json index ace8c0caaa..01df490163 100644 --- a/targets/py32f001cxx.json +++ b/targets/py32f001cxx.json @@ -5,7 +5,8 @@ "build-tags": [ "py32f001cxx", "py32_no_gpio_afrh", - "py32_hsi_fs_literal4" + "py32_hsi_fs_literal4", + "py32_usart1_clock_literal" ], "extra-files": [ "src/device/py32/py32f001cxx.s" diff --git a/targets/py32f001xx.json b/targets/py32f001xx.json index 58248f3e1b..b53ec8bbb0 100644 --- a/targets/py32f001xx.json +++ b/targets/py32f001xx.json @@ -3,7 +3,8 @@ "py32" ], "build-tags": [ - "py32f001xx" + "py32f001xx", + "py32_usart1_clock_literal" ], "extra-files": [ "src/device/py32/py32f001xx.s" diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index 37b73e2604..df3d58e8ac 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -59,6 +59,7 @@ var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") var usartUnnumbered = familySet("py32f410xx") +var usart1ClockLiteral = familySet("py32f001cxx", "py32f001xx") var uartClockAPB2 = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartNoInterrupt = familySet("py32f410xx") @@ -86,6 +87,7 @@ func familyBuildTags(family string) []string { {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, {"py32_usart_unnumbered", usartUnnumbered}, + {"py32_usart1_clock_literal", usart1ClockLiteral}, {"py32_uart_clock_apb2", uartClockAPB2}, {"py32_uart_no_interrupt", uartNoInterrupt}, } diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index 5d59113be0..008ce029fe 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -81,8 +81,8 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32f030x8.json"), "py32f030xx", "targets/py32f030x8.ld", "pyocd load -t py32f030x8 {bin}") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") - checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") - checkBuildTags(t, filepath.Join(out, "py32f001xx.json"), "py32f001xx") + checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") + checkBuildTags(t, filepath.Join(out, "py32f001xx.json"), "py32f001xx", "py32_usart1_clock_literal") checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx") checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") From a3c99460db8f4f522f9aa5f1ff40e68adbaf2ac1 Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Thu, 27 Aug 2026 20:57:09 +0200 Subject: [PATCH 60/62] machine/py32: name T020 8-bit UART mode --- lib/py32-svd | 2 +- src/machine/machine_py32_uart_type.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/py32-svd b/lib/py32-svd index 93af0a9a84..f540a90774 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit 93af0a9a8481e0b3c8405fa77db18c5a1e1d7562 +Subproject commit f540a90774beec6898a9ae2b8df6a86d90cc47bf diff --git a/src/machine/machine_py32_uart_type.go b/src/machine/machine_py32_uart_type.go index 97ce20fd8a..7764e09514 100644 --- a/src/machine/machine_py32_uart_type.go +++ b/src/machine/machine_py32_uart_type.go @@ -27,7 +27,7 @@ func (uart *UART) Configure(config UARTConfig) error { } py32.RCC.APBENR1.SetBits(py32.RCC_APBENR1_UART1EN) - uart.Bus.CR1.Set(py32.UART_CR1_M_Msk) + uart.Bus.CR1.Set(py32.UART_CR1_M_Char8Bits) uart.Bus.CR2.Set(py32.UART_CR2_RXNEIE) uart.Bus.CR3.Set(0) divider := (CPUFrequency() + config.BaudRate*8) / (config.BaudRate * 16) From 733cd226877c0fb1ef3c952429967ce0640c959f Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 28 Aug 2026 10:16:40 +0200 Subject: [PATCH 61/62] ci: include PY32 in sharded smoke tests --- .github/workflows/linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index ce3f0acb49..662d6180ec 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -193,7 +193,7 @@ jobs: # Balanced with the measured build time of each group, so that the # shards finish at about the same time. group: - - smoketest-rp2xxx smoketest-selftest smoketest-wasm-sim + - smoketest-rp2xxx smoketest-selftest smoketest-wasm-sim smoketest-py32 - smoketest-esp smoketest-riscv smoketest-flags - smoketest-examples smoketest-nxp smoketest-pwm-usb smoketest-avr - smoketest-samd smoketest-stm32 smoketest-nrf smoketest-wasm From dcbcdfaf660949f48aca5236558d2f4774800a9e Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Fri, 28 Aug 2026 12:05:23 +0200 Subject: [PATCH 62/62] runtime: remove PY32 HSI frequency workaround --- lib/py32-svd | 2 +- src/runtime/runtime_py32_hsi.go | 2 +- src/runtime/runtime_py32_hsi_literal4.go | 10 ---------- targets/py32f001cxx.json | 1 - targets/py32f002cxx.json | 3 +-- tools/gen-py32-targets/main.go | 2 -- tools/gen-py32-targets/main_test.go | 4 ++-- 7 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 src/runtime/runtime_py32_hsi_literal4.go diff --git a/lib/py32-svd b/lib/py32-svd index f540a90774..6aa7396c1d 160000 --- a/lib/py32-svd +++ b/lib/py32-svd @@ -1 +1 @@ -Subproject commit f540a90774beec6898a9ae2b8df6a86d90cc47bf +Subproject commit 6aa7396c1d4d20be61cc62f283fa3835665c7361 diff --git a/src/runtime/runtime_py32_hsi.go b/src/runtime/runtime_py32_hsi.go index dd2d0bb42a..3e13c817bd 100644 --- a/src/runtime/runtime_py32_hsi.go +++ b/src/runtime/runtime_py32_hsi.go @@ -1,4 +1,4 @@ -//go:build py32 && !py32_hsi_fs_op && !py32_hsi_fs_literal4 && !py32_no_hsi_fs +//go:build py32 && !py32_hsi_fs_op && !py32_no_hsi_fs package runtime diff --git a/src/runtime/runtime_py32_hsi_literal4.go b/src/runtime/runtime_py32_hsi_literal4.go deleted file mode 100644 index 0fe55f8f23..0000000000 --- a/src/runtime/runtime_py32_hsi_literal4.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build py32 && py32_hsi_fs_literal4 - -package runtime - -import "device/py32" - -// The affected vendor headers do not provide usable value constants. -func configureHSI() { - py32.RCC.SetICSCR_HSI_FS(4) -} diff --git a/targets/py32f001cxx.json b/targets/py32f001cxx.json index 01df490163..86836864cc 100644 --- a/targets/py32f001cxx.json +++ b/targets/py32f001cxx.json @@ -5,7 +5,6 @@ "build-tags": [ "py32f001cxx", "py32_no_gpio_afrh", - "py32_hsi_fs_literal4", "py32_usart1_clock_literal" ], "extra-files": [ diff --git a/targets/py32f002cxx.json b/targets/py32f002cxx.json index 218270e8c6..e7f83f92f3 100644 --- a/targets/py32f002cxx.json +++ b/targets/py32f002cxx.json @@ -4,8 +4,7 @@ ], "build-tags": [ "py32f002cxx", - "py32_no_gpio_afrh", - "py32_hsi_fs_literal4" + "py32_no_gpio_afrh" ], "extra-files": [ "src/device/py32/py32f002cxx.s" diff --git a/tools/gen-py32-targets/main.go b/tools/gen-py32-targets/main.go index df3d58e8ac..e0a159447d 100644 --- a/tools/gen-py32-targets/main.go +++ b/tools/gen-py32-targets/main.go @@ -54,7 +54,6 @@ var gpioOSPDDER = familySet("py32e407xx", "py32f410xx", "py32l090xx", "py32t090x var gpioClockAHB2 = familySet("py32e407xx", "py32f403xx") var gpioClockAHB = familySet("py32f410xx") var hsiFSOP = familySet("py32l090xx", "py32t090xx", "py32t092xx") -var hsiFSLiteral4 = familySet("py32f001cxx", "py32f002cxx") var noHSIFS = familySet("py32e407xx", "py32f403xx", "py32f410xx") var uartType = familySet("py32t020xx") var usartSplitData = familySet("py32e407xx") @@ -82,7 +81,6 @@ func familyBuildTags(family string) []string { {"py32_gpio_clock_ahb2", gpioClockAHB2}, {"py32_gpio_clock_ahb", gpioClockAHB}, {"py32_hsi_fs_op", hsiFSOP}, - {"py32_hsi_fs_literal4", hsiFSLiteral4}, {"py32_no_hsi_fs", noHSIFS}, {"py32_uart_type", uartType}, {"py32_usart_split_data", usartSplitData}, diff --git a/tools/gen-py32-targets/main_test.go b/tools/gen-py32-targets/main_test.go index 008ce029fe..6d93caacf6 100644 --- a/tools/gen-py32-targets/main_test.go +++ b/tools/gen-py32-targets/main_test.go @@ -81,9 +81,9 @@ func TestGenerate(t *testing.T) { checkTarget(t, filepath.Join(out, "py32f030x8.json"), "py32f030xx", "targets/py32f030x8.ld", "pyocd load -t py32f030x8 {bin}") checkTarget(t, filepath.Join(out, "py32f410xx.json"), "py32-m4", "", "") checkBuildTags(t, filepath.Join(out, "py32e407xx.json"), "py32e407xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb2", "py32_no_hsi_fs", "py32_usart_split_data", "py32_uart_clock_apb2") - checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4", "py32_usart1_clock_literal") + checkBuildTags(t, filepath.Join(out, "py32f001cxx.json"), "py32f001cxx", "py32_no_gpio_afrh", "py32_usart1_clock_literal") checkBuildTags(t, filepath.Join(out, "py32f001xx.json"), "py32f001xx", "py32_usart1_clock_literal") - checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh", "py32_hsi_fs_literal4") + checkBuildTags(t, filepath.Join(out, "py32f002cxx.json"), "py32f002cxx", "py32_no_gpio_afrh") checkBuildTags(t, filepath.Join(out, "py32f032xx.json"), "py32f032xx") checkBuildTags(t, filepath.Join(out, "py32f410xx.json"), "py32f410xx", "py32_gpio_ospdder", "py32_gpio_clock_ahb", "py32_no_hsi_fs", "py32_usart_unnumbered", "py32_uart_clock_apb2", "py32_uart_no_interrupt") checkBuildTags(t, filepath.Join(out, "py32t020xx.json"), "py32t020xx", "py32_uart_type")