mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-30 17:29:04 +00:00
Puya PY32F MCU support (#5106)
* pinout yamls removed * machine: implement default UART pin configuration for Embedfire boards * flash command moved to chip level so VS Code plugin can select bare chip * machine: add support for alternate pin mode configuration * add build targets for embedfire on py32 * add support for embedfire target in GNUmakefile for py32 * 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. * update subproject commit reference in py32-svd * refactor: update CPU frequency handling in machine and runtime packages * refactor: replace ConfigureUARTPin function with direct pin configuration in UART setup * SetAltFunc documentation for GPIO pin alternate functions * refactor: improve UART write and flush error handling with timeout * 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). * 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. * Add targets for all PY32 CMSIS devices * Support all PY32 register layout variants * machine/py32: use generated register definitions * machine/py32: fix alternate-function documentation * machine/py32: report the configured CPU frequency * machine/py32: use unsafe.Add for GPIO ports * machine/py32: bound and yield UART polling * machine/py32: configure UART pins from UARTConfig * build: use the current PY32 SVD repository URL * test: cover PY32 UART register layouts * machine/py32: restore dynamic CPU frequency tracking * machine/py32: share the USART TX-ready bit * targets/py32: scale system stacks with RAM * machine/py32: keep clock state internal * targets/py32: normalize generated metadata * machine/py32: normalize GPIO configuration * machine/py32: fix T020 UART setup * machine/py32: reduce clock variant files * machine/py32: clean up UART variants * machine/py32: decouple UART clock capability * lib/py32-svd: use organization repository * runtime/py32: name 24MHz HSI encodings * machine/py32: derive startup clock from capability * machine/py32: use generated USART clock mask * machine/py32: name T020 8-bit UART mode * ci: include PY32 in sharded smoke tests * runtime: remove PY32 HSI frequency workaround
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/tinygo-org/py32-svd.git
|
||||
|
||||
@@ -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{
|
||||
|
||||
Submodule
+1
Submodule lib/py32-svd added at 6aa7396c1d
+9
-2
@@ -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-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 ## 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,10 @@ 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
|
||||
|
||||
gen-target-py32: ## Generate PY32 target and linker definitions
|
||||
$(GO) run ./tools/gen-py32-targets
|
||||
|
||||
@@ -19,6 +19,7 @@ SMOKETEST_SUBTARGETS = \
|
||||
smoketest-rp2xxx \
|
||||
smoketest-pwm-usb \
|
||||
smoketest-stm32 \
|
||||
smoketest-py32 \
|
||||
smoketest-avr \
|
||||
smoketest-esp \
|
||||
smoketest-riscv \
|
||||
@@ -403,6 +404,37 @@ ifneq ($(STM32), 0)
|
||||
@$(MD5SUM) $(SMOKE_OUT).hex
|
||||
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
|
||||
@$(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
|
||||
$(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
|
||||
$(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
|
||||
@$(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
|
||||
smoketest-avr: | build/smoke
|
||||
$(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=atmega328pb examples/blinkm
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//go:build embedfire_py32f002b
|
||||
|
||||
// Pin mappings for the Embedfire PY32F002B board.
|
||||
|
||||
package machine
|
||||
|
||||
// LEDs
|
||||
const (
|
||||
LED1 = PA1
|
||||
LED2 = PA5
|
||||
LED3 = PA4
|
||||
LED = LED2
|
||||
)
|
||||
|
||||
// Buttons
|
||||
const (
|
||||
KEY1 = PA3
|
||||
KEY2 = PA0
|
||||
)
|
||||
|
||||
const (
|
||||
UART_TX_PIN = PA6
|
||||
UART_RX_PIN = PA7
|
||||
)
|
||||
|
||||
func defaultUARTPins() (Pin, Pin) {
|
||||
return UART_TX_PIN, UART_RX_PIN
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//go:build embedfire_py32f030
|
||||
|
||||
// Pin mappings for the Embedfire PY32F030 board.
|
||||
|
||||
package machine
|
||||
|
||||
// LEDs
|
||||
const (
|
||||
LED1 = PA2
|
||||
LED2 = PA3
|
||||
LED3 = PA4
|
||||
LED = LED2
|
||||
)
|
||||
|
||||
// Buttons
|
||||
const (
|
||||
KEY1 = PA5
|
||||
KEY2 = PA6
|
||||
)
|
||||
|
||||
const (
|
||||
UART_TX_PIN = PA7
|
||||
UART_RX_PIN = PA8
|
||||
)
|
||||
|
||||
func defaultUARTPins() (Pin, Pin) {
|
||||
return UART_TX_PIN, UART_RX_PIN
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//go:build py32
|
||||
|
||||
package machine
|
||||
|
||||
var cpuFrequencyHz uint32 = defaultCPUFrequencyHz
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
return cpuFrequencyHz
|
||||
}
|
||||
|
||||
func setCPUFrequency(frequency uint32) {
|
||||
cpuFrequencyHz = frequency
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
//go:build py32 && !py32_no_hsi_fs
|
||||
|
||||
package machine
|
||||
|
||||
const defaultCPUFrequencyHz = 24_000_000
|
||||
@@ -0,0 +1,5 @@
|
||||
//go:build py32 && py32_no_hsi_fs
|
||||
|
||||
package machine
|
||||
|
||||
const defaultCPUFrequencyHz = 8_000_000
|
||||
@@ -0,0 +1,226 @@
|
||||
//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.getPortNumber
|
||||
// can keep using simple division by 16.
|
||||
const (
|
||||
portA Pin = iota * 16
|
||||
portB
|
||||
portC
|
||||
portD
|
||||
portE
|
||||
portF
|
||||
)
|
||||
|
||||
const (
|
||||
PA0 Pin = portA + iota
|
||||
PA1
|
||||
PA2
|
||||
PA3
|
||||
PA4
|
||||
PA5
|
||||
PA6
|
||||
PA7
|
||||
PA8
|
||||
PA9
|
||||
PA10
|
||||
PA11
|
||||
PA12
|
||||
PA13
|
||||
PA14
|
||||
PA15
|
||||
)
|
||||
|
||||
const (
|
||||
PB0 Pin = portB + iota
|
||||
PB1
|
||||
PB2
|
||||
PB3
|
||||
PB4
|
||||
PB5
|
||||
PB6
|
||||
PB7
|
||||
PB8
|
||||
PB9
|
||||
PB10
|
||||
PB11
|
||||
PB12
|
||||
PB13
|
||||
PB14
|
||||
PB15
|
||||
)
|
||||
|
||||
const (
|
||||
PC0 Pin = portC + iota
|
||||
PC1
|
||||
PC2
|
||||
PC3
|
||||
PC4
|
||||
PC5
|
||||
PC6
|
||||
PC7
|
||||
PC8
|
||||
PC9
|
||||
PC10
|
||||
PC11
|
||||
PC12
|
||||
PC13
|
||||
PC14
|
||||
PC15
|
||||
)
|
||||
|
||||
const (
|
||||
PD0 Pin = portD + iota
|
||||
PD1
|
||||
PD2
|
||||
PD3
|
||||
PD4
|
||||
PD5
|
||||
PD6
|
||||
PD7
|
||||
PD8
|
||||
PD9
|
||||
PD10
|
||||
PD11
|
||||
PD12
|
||||
PD13
|
||||
PD14
|
||||
PD15
|
||||
)
|
||||
|
||||
const (
|
||||
PE0 Pin = portE + iota
|
||||
PE1
|
||||
PE2
|
||||
PE3
|
||||
PE4
|
||||
PE5
|
||||
PE6
|
||||
PE7
|
||||
PE8
|
||||
PE9
|
||||
PE10
|
||||
PE11
|
||||
PE12
|
||||
PE13
|
||||
PE14
|
||||
PE15
|
||||
)
|
||||
|
||||
const (
|
||||
PF0 Pin = portF + iota
|
||||
PF1
|
||||
PF2
|
||||
PF3
|
||||
PF4
|
||||
PF5
|
||||
PF6
|
||||
PF7
|
||||
PF8
|
||||
PF9
|
||||
PF10
|
||||
PF11
|
||||
PF12
|
||||
PF13
|
||||
PF14
|
||||
PF15
|
||||
)
|
||||
|
||||
const (
|
||||
PinOutput PinMode = iota
|
||||
PinInput
|
||||
PinInputPulldown
|
||||
PinInputPullup
|
||||
PinInputAnalog
|
||||
PinAlternate
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
gpioPullFloating = 0
|
||||
gpioPullUp = 1
|
||||
gpioPullDown = 2
|
||||
gpioPullMask = py32.GPIO_PUPDR_PUPD0_Msk
|
||||
|
||||
gpioOutputSpeedLow = 0
|
||||
gpioOutputSpeedMedium = 1
|
||||
gpioOutputSpeedHigh = 2
|
||||
gpioOutputSpeedVeryHigh = 3
|
||||
|
||||
gpioOutputTypePushPull = 0
|
||||
gpioOutputTypeMask = py32.GPIO_OTYPER_OT0_Msk
|
||||
)
|
||||
|
||||
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.Add(unsafe.Pointer(py32.GPIOA), offset)), p.getPinNumber()
|
||||
}
|
||||
|
||||
func (p Pin) Set(high bool) {
|
||||
port, pin := p.getPort()
|
||||
if high {
|
||||
port.BSRR.Set(py32.GPIO_BSRR_BS0 << pin)
|
||||
} else {
|
||||
port.BSRR.Set(py32.GPIO_BSRR_BR0 << pin)
|
||||
}
|
||||
}
|
||||
|
||||
func (p Pin) Get() bool {
|
||||
port, pin := p.getPort()
|
||||
val := port.IDR.Get() & (py32.GPIO_IDR_ID0 << pin)
|
||||
return val > 0
|
||||
}
|
||||
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
p.enableClock()
|
||||
port, pin := p.getPort()
|
||||
pos := pin * 2
|
||||
|
||||
switch config.Mode {
|
||||
|
||||
case PinInput:
|
||||
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(gpioOutputTypePushPull, gpioOutputTypeMask, 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.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
|
||||
port.OTYPER.ReplaceBits(gpioOutputTypePushPull, gpioOutputTypeMask, pos>>1)
|
||||
setPinOutputSpeed(port, gpioOutputSpeedHigh, pos)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
//go:build py32 && !py32_no_gpio_afrh
|
||||
|
||||
package machine
|
||||
|
||||
import "device/py32"
|
||||
|
||||
// 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 {
|
||||
port.AFRH.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4)
|
||||
} else {
|
||||
port.AFRL.ReplaceBits(uint32(af), py32.GPIO_AFRL_AFSEL0_Msk, (pin%8)*4)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build py32 && !py32_gpio_clock_ahb2 && !py32_gpio_clock_ahb
|
||||
|
||||
package machine
|
||||
|
||||
import "device/py32"
|
||||
|
||||
func (p Pin) enableClock() {
|
||||
py32.RCC.IOPENR.SetBits(py32.RCC_IOPENR_GPIOAEN << p.getPortNumber())
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build py32 && py32_gpio_clock_ahb
|
||||
|
||||
package machine
|
||||
|
||||
import "device/py32"
|
||||
|
||||
func (p Pin) enableClock() {
|
||||
py32.RCC.AHBENR.SetBits(py32.RCC_AHBENR_IOPAEN << p.getPortNumber())
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//go:build py32 && py32_no_gpio_afrh
|
||||
|
||||
package machine
|
||||
|
||||
import "device/py32"
|
||||
|
||||
// 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)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//go:build py32 && !py32_gpio_ospdder
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//go:build py32 && py32_gpio_ospdder
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//go:build py32 && !py32_uart_type
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/py32"
|
||||
"runtime/interrupt"
|
||||
)
|
||||
|
||||
// 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)
|
||||
txRetries uint32
|
||||
num uint8
|
||||
}
|
||||
|
||||
// DefaultUART is the first USART (USART1) and backs machine.Serial.
|
||||
var DefaultUART = &UART{Bus: defaultUSART(), Buffer: NewRingBuffer(), setup: setupUSART1, 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
|
||||
}
|
||||
|
||||
// Enable the peripheral clock and hook its RX interrupt.
|
||||
uart.setup(uart)
|
||||
|
||||
// Reset control registers to a known state.
|
||||
uart.Bus.CR1.Set(0)
|
||||
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)
|
||||
|
||||
// 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)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
enableUSART1Clock()
|
||||
configureUSART1Interrupt(uart)
|
||||
}
|
||||
|
||||
func handleUSART1Interrupt(interrupt.Interrupt) {
|
||||
usart1RX.Receive(uint8(readUSARTData(usart1RX.Bus)))
|
||||
}
|
||||
|
||||
// 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 := uart.txRetries
|
||||
for retries > 0 && !usartTXReady(uart.Bus) {
|
||||
uartYield()
|
||||
retries--
|
||||
}
|
||||
if retries <= 0 {
|
||||
return errUARTWriteTimeout
|
||||
}
|
||||
writeUSARTData(uart.Bus, uint32(c))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (uart *UART) flush() {
|
||||
retries := uart.txRetries
|
||||
for retries > 0 && !usartTXComplete(uart.Bus) {
|
||||
uartYield()
|
||||
retries--
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//go:build py32 && (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, num: 2}
|
||||
|
||||
// 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(readUSARTData(usart2RX.Bus)))
|
||||
}
|
||||
|
||||
// usart2RX is the UART serviced by handleUSART2Interrupt, set by setupUSART2.
|
||||
var usart2RX *UART
|
||||
@@ -0,0 +1,9 @@
|
||||
//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(py32.RCC_APBENR2_USART1EN)
|
||||
}
|
||||
@@ -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(py32.RCC_APB2ENR_USART1EN)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//go:build py32
|
||||
|
||||
package machine
|
||||
|
||||
import "runtime/interrupt"
|
||||
|
||||
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 (
|
||||
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
|
||||
if retries < 10 {
|
||||
return 10
|
||||
}
|
||||
return retries
|
||||
}
|
||||
|
||||
func uartYield() {
|
||||
if !interrupt.In() {
|
||||
gosched()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
//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 {
|
||||
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 {
|
||||
return bus.SR.Get()&py32.USART_SR_TC != 0
|
||||
}
|
||||
@@ -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()&py32.USART_SR_TXE_TXFNF != 0
|
||||
}
|
||||
|
||||
func usartTXComplete(bus *py32.USART_Type) bool {
|
||||
return bus.SR.Get()&py32.USART_SR_TC != 0
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build py32 && !py32_default_uart_pins
|
||||
|
||||
package machine
|
||||
|
||||
func defaultUARTPins() (Pin, Pin) {
|
||||
return NoPin, NoPin
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//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
|
||||
txRetries uint32
|
||||
num uint8
|
||||
}
|
||||
|
||||
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(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)
|
||||
uart.Bus.BRR.Set(divider)
|
||||
|
||||
uart.irq = interrupt.New(py32.IRQ_UART1, handleUART1Interrupt)
|
||||
uart.irq.SetPriority(0xc0)
|
||||
uart.irq.Enable()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleUART1Interrupt(interrupt.Interrupt) {
|
||||
DefaultUART.Receive(uint8(DefaultUART.Bus.DR.Get()))
|
||||
}
|
||||
|
||||
func (uart *UART) writeByte(c byte) error {
|
||||
retries := uart.txRetries
|
||||
for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TDRE == 0 {
|
||||
uartYield()
|
||||
retries--
|
||||
}
|
||||
if retries <= 0 {
|
||||
return errUARTWriteTimeout
|
||||
}
|
||||
uart.Bus.DR.Set(uint32(c))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (uart *UART) flush() {
|
||||
retries := uart.txRetries
|
||||
for retries > 0 && uart.Bus.SR.Get()&py32.UART_SR_TXE == 0 {
|
||||
uartYield()
|
||||
retries--
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build py32 && py32_usart_unnumbered
|
||||
|
||||
package machine
|
||||
|
||||
import "device/py32"
|
||||
|
||||
func defaultUSART() *py32.USART_Type {
|
||||
return py32.USART
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build atsamd21 || nrf51
|
||||
//go:build atsamd21 || nrf51 || py32
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cortexm && !atsamd21 && !nrf51
|
||||
//go:build cortexm && !atsamd21 && !nrf51 && !py32
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
//go:build py32
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
"machine"
|
||||
"runtime/volatile"
|
||||
)
|
||||
|
||||
var tickCounter volatile.Register64
|
||||
|
||||
//export Reset_Handler
|
||||
func main() {
|
||||
preinit()
|
||||
|
||||
configureHSI()
|
||||
|
||||
configureSystemTimer()
|
||||
machine.InitSerial()
|
||||
|
||||
run()
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// configureSystemTimer configures SysTick for 1ms ticks.
|
||||
func configureSystemTimer() {
|
||||
arm.SetupSystemTimer(machine.CPUFrequency() / 1000)
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(value timeUnit) int64 {
|
||||
return int64(value * 1000_000)
|
||||
}
|
||||
|
||||
func nanosecondsToTicks(ns int64) timeUnit {
|
||||
return timeUnit(ns / 1000_000)
|
||||
}
|
||||
|
||||
//go:linkname ticks runtime.ticks
|
||||
func ticks() timeUnit {
|
||||
return timeUnit(tickCounter.Get())
|
||||
}
|
||||
|
||||
func sleepTicks(d timeUnit) {
|
||||
if d <= 0 {
|
||||
return
|
||||
}
|
||||
start := ticks()
|
||||
stop := start + d
|
||||
for ticks() < stop {
|
||||
waitForEvents()
|
||||
}
|
||||
}
|
||||
|
||||
func waitForEvents() {
|
||||
arm.Asm("wfe")
|
||||
}
|
||||
|
||||
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
|
||||
func handleSysTick() {
|
||||
tickCounter.Set(tickCounter.Get() + 1)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build py32 && !py32_hsi_fs_op && !py32_no_hsi_fs
|
||||
|
||||
package runtime
|
||||
|
||||
import "device/py32"
|
||||
|
||||
func configureHSI() {
|
||||
py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz)
|
||||
}
|
||||
@@ -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 their
|
||||
// vendor-defined 8 MHz reset clock instead of writing an unverified encoding.
|
||||
func configureHSI() {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//go:build py32 && py32_hsi_fs_op
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002bx5"
|
||||
],
|
||||
"build-tags": [
|
||||
"embedfire_py32f002b",
|
||||
"py32_default_uart_pins"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f030x8"
|
||||
],
|
||||
"build-tags": [
|
||||
"embedfire_py32f030",
|
||||
"py32_default_uart_pins"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"cortex-m4"
|
||||
],
|
||||
"scheduler": "none",
|
||||
"gc": "none",
|
||||
"serial": "uart",
|
||||
"build-tags": [
|
||||
"py32"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"cortex-m0plus"
|
||||
],
|
||||
"scheduler": "none",
|
||||
"gc": "none",
|
||||
"serial": "uart",
|
||||
"build-tags": [
|
||||
"py32"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32e407xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32e407xc"
|
||||
],
|
||||
"linkerscript": "targets/py32e407xc.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x40000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1c000
|
||||
}
|
||||
|
||||
_stack_size = 4K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32e407xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32e407xd"
|
||||
],
|
||||
"linkerscript": "targets/py32e407xd.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x60000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000
|
||||
}
|
||||
|
||||
_stack_size = 4K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32e407xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32e407xe"
|
||||
],
|
||||
"linkerscript": "targets/py32e407xe.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x80000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x24000
|
||||
}
|
||||
|
||||
_stack_size = 4K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32-m4"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32e407xx",
|
||||
"py32_gpio_ospdder",
|
||||
"py32_gpio_clock_ahb2",
|
||||
"py32_no_hsi_fs",
|
||||
"py32_usart_split_data",
|
||||
"py32_uart_clock_apb2"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32e407xx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f001cxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f001cx4"
|
||||
],
|
||||
"linkerscript": "targets/py32f001cx4.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f001cxx",
|
||||
"py32_no_gpio_afrh",
|
||||
"py32_usart1_clock_literal"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f001cxx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f001xx",
|
||||
"py32_usart1_clock_literal"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f001xx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002axx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002ax5"
|
||||
],
|
||||
"linkerscript": "targets/py32f002ax5.ld",
|
||||
"flash-command": "pyocd load -t py32f002ax5 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x5000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002axx"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f002axx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002bxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002bx5"
|
||||
],
|
||||
"linkerscript": "targets/py32f002bx5.ld",
|
||||
"flash-command": "pyocd load -t py32f002bx5 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002bxx",
|
||||
"py32_no_gpio_afrh"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f002bxx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002cxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002cx5"
|
||||
],
|
||||
"linkerscript": "targets/py32f002cx5.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002cxx",
|
||||
"py32_no_gpio_afrh"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f002cxx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002xxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002xx2"
|
||||
],
|
||||
"linkerscript": "targets/py32f002xx2.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x2000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002xxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002xx4"
|
||||
],
|
||||
"linkerscript": "targets/py32f002xx4.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002xxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002xx5"
|
||||
],
|
||||
"linkerscript": "targets/py32f002xx5.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x6000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002xxx",
|
||||
"py32_no_gpio_afrh"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f002xxx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f002zxx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002zx4"
|
||||
],
|
||||
"linkerscript": "targets/py32f002zx4.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc00
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f002zxx",
|
||||
"py32_no_gpio_afrh"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f002zxx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f003xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f003x4"
|
||||
],
|
||||
"linkerscript": "targets/py32f003x4.ld",
|
||||
"flash-command": "pyocd load -t py32f003x4 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f003xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f003x6"
|
||||
],
|
||||
"linkerscript": "targets/py32f003x6.ld",
|
||||
"flash-command": "pyocd load -t py32f003x6 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f003xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f003x7"
|
||||
],
|
||||
"linkerscript": "targets/py32f003x7.ld",
|
||||
"flash-command": "pyocd load -t py32f003x7 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0xc000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f003xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f003x8"
|
||||
],
|
||||
"linkerscript": "targets/py32f003x8.ld",
|
||||
"flash-command": "pyocd load -t py32f003x8 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f003xx"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f003xx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f021xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f021x8"
|
||||
],
|
||||
"linkerscript": "targets/py32f021x8.ld"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f021xx"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f021xx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f030xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f030x4"
|
||||
],
|
||||
"linkerscript": "targets/py32f030x4.ld",
|
||||
"flash-command": "pyocd load -t py32f030x4 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x4000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x800
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f030xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f030x6"
|
||||
],
|
||||
"linkerscript": "targets/py32f030x6.ld",
|
||||
"flash-command": "pyocd load -t py32f030x6 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x8000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1000
|
||||
}
|
||||
|
||||
_stack_size = 1K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f030xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f030x7"
|
||||
],
|
||||
"linkerscript": "targets/py32f030x7.ld",
|
||||
"flash-command": "pyocd load -t py32f030x7 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0xc000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x1800
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f030xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f030x8"
|
||||
],
|
||||
"linkerscript": "targets/py32f030x8.ld",
|
||||
"flash-command": "pyocd load -t py32f030x8 {bin}"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH_TEXT (rx) : ORIGIN = 0x8000000, LENGTH = 0x10000
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x2000
|
||||
}
|
||||
|
||||
_stack_size = 2K;
|
||||
|
||||
INCLUDE "targets/arm.ld"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f030xx"
|
||||
],
|
||||
"extra-files": [
|
||||
"src/device/py32/py32f030xx.s"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"inherits": [
|
||||
"py32f031xx"
|
||||
],
|
||||
"build-tags": [
|
||||
"py32f031x4"
|
||||
],
|
||||
"linkerscript": "targets/py32f031x4.ld"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user