mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-31 17:59:03 +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
|
# Balanced with the measured build time of each group, so that the
|
||||||
# shards finish at about the same time.
|
# shards finish at about the same time.
|
||||||
group:
|
group:
|
||||||
- smoketest-rp2xxx smoketest-selftest smoketest-wasm-sim
|
- smoketest-rp2xxx smoketest-selftest smoketest-wasm-sim smoketest-py32
|
||||||
- smoketest-esp smoketest-riscv smoketest-flags
|
- smoketest-esp smoketest-riscv smoketest-flags
|
||||||
- smoketest-examples smoketest-nxp smoketest-pwm-usb smoketest-avr
|
- smoketest-examples smoketest-nxp smoketest-pwm-usb smoketest-avr
|
||||||
- smoketest-samd smoketest-stm32 smoketest-nrf smoketest-wasm
|
- smoketest-samd smoketest-stm32 smoketest-nrf smoketest-wasm
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ src/device/renesas/*.go
|
|||||||
src/device/renesas/*.s
|
src/device/renesas/*.s
|
||||||
src/device/rp/*.go
|
src/device/rp/*.go
|
||||||
src/device/rp/*.s
|
src/device/rp/*.s
|
||||||
|
src/device/py32/*.go
|
||||||
|
src/device/py32/*.s
|
||||||
./vendor
|
./vendor
|
||||||
llvm-build
|
llvm-build
|
||||||
llvm-project
|
llvm-project
|
||||||
|
|||||||
@@ -41,3 +41,6 @@
|
|||||||
[submodule "lib/bdwgc"]
|
[submodule "lib/bdwgc"]
|
||||||
path = lib/bdwgc
|
path = lib/bdwgc
|
||||||
url = https://github.com/ivmai/bdwgc.git
|
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
|
package compileopts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"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) {
|
func TestOverrideProperties(t *testing.T) {
|
||||||
baseAutoStackSize := true
|
baseAutoStackSize := true
|
||||||
base := &TargetSpec{
|
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 \
|
.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-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)
|
ifneq ($(RENESAS), 0)
|
||||||
gen-device: gen-device-renesas
|
gen-device: gen-device-renesas
|
||||||
endif
|
endif
|
||||||
@@ -58,3 +58,10 @@ gen-device-rp: build/gen-device-svd
|
|||||||
gen-device-renesas: 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/
|
./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
|
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-rp2xxx \
|
||||||
smoketest-pwm-usb \
|
smoketest-pwm-usb \
|
||||||
smoketest-stm32 \
|
smoketest-stm32 \
|
||||||
|
smoketest-py32 \
|
||||||
smoketest-avr \
|
smoketest-avr \
|
||||||
smoketest-esp \
|
smoketest-esp \
|
||||||
smoketest-riscv \
|
smoketest-riscv \
|
||||||
@@ -403,6 +404,37 @@ ifneq ($(STM32), 0)
|
|||||||
@$(MD5SUM) $(SMOKE_OUT).hex
|
@$(MD5SUM) $(SMOKE_OUT).hex
|
||||||
endif
|
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: SMOKE_OUT = build/smoke/avr
|
||||||
smoketest-avr: | build/smoke
|
smoketest-avr: | build/smoke
|
||||||
$(TINYGO) build -size short -o $(SMOKE_OUT).hex -target=atmega328pb examples/blinkm
|
$(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
|
package machine
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build atsamd21 || nrf51
|
//go:build atsamd21 || nrf51 || py32
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build cortexm && !atsamd21 && !nrf51
|
//go:build cortexm && !atsamd21 && !nrf51 && !py32
|
||||||
|
|
||||||
package runtime
|
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