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:
Pavel Burgr
2026-08-29 08:41:43 +02:00
committed by GitHub
parent f6e502e121
commit b420a8be17
272 changed files with 3744 additions and 9 deletions
+1 -1
View File
@@ -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
+2
View File
@@ -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
+3
View File
@@ -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
+34
View File
@@ -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
View File
@@ -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
+32
View File
@@ -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
+28
View File
@@ -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
}
+28
View File
@@ -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
}
+13
View File
@@ -0,0 +1,13 @@
//go:build py32
package machine
var cpuFrequencyHz uint32 = defaultCPUFrequencyHz
func CPUFrequency() uint32 {
return cpuFrequencyHz
}
func setCPUFrequency(frequency uint32) {
cpuFrequencyHz = frequency
}
+5
View File
@@ -0,0 +1,5 @@
//go:build py32 && !py32_no_hsi_fs
package machine
const defaultCPUFrequencyHz = 24_000_000
+5
View File
@@ -0,0 +1,5 @@
//go:build py32 && py32_no_hsi_fs
package machine
const defaultCPUFrequencyHz = 8_000_000
+226
View File
@@ -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)
}
}
+17
View File
@@ -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)
}
}
+9
View File
@@ -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())
}
+13
View File
@@ -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)
}
+14
View File
@@ -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)
}
+94
View File
@@ -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--
}
}
+30
View File
@@ -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
+9
View File
@@ -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)
}
+58
View File
@@ -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()
}
}
+22
View File
@@ -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
}
+65
View File
@@ -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--
}
}
+9
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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
+74
View File
@@ -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)
}
+9
View File
@@ -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)
}
+8
View File
@@ -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() {
}
+11
View File
@@ -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)
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002bx5"
],
"build-tags": [
"embedfire_py32f002b",
"py32_default_uart_pins"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f030x8"
],
"build-tags": [
"embedfire_py32f030",
"py32_default_uart_pins"
]
}
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"cortex-m4"
],
"scheduler": "none",
"gc": "none",
"serial": "uart",
"build-tags": [
"py32"
]
}
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"cortex-m0plus"
],
"scheduler": "none",
"gc": "none",
"serial": "uart",
"build-tags": [
"py32"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32e407xx"
],
"build-tags": [
"py32e407xc"
],
"linkerscript": "targets/py32e407xc.ld"
}
+9
View File
@@ -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"
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32e407xx"
],
"build-tags": [
"py32e407xd"
],
"linkerscript": "targets/py32e407xd.ld"
}
+9
View File
@@ -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"
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32e407xx"
],
"build-tags": [
"py32e407xe"
],
"linkerscript": "targets/py32e407xe.ld"
}
+9
View File
@@ -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"
+16
View File
@@ -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"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f001cxx"
],
"build-tags": [
"py32f001cx4"
],
"linkerscript": "targets/py32f001cx4.ld"
}
+9
View File
@@ -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"
+13
View File
@@ -0,0 +1,13 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f001cxx",
"py32_no_gpio_afrh",
"py32_usart1_clock_literal"
],
"extra-files": [
"src/device/py32/py32f001cxx.s"
]
}
+12
View File
@@ -0,0 +1,12 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f001xx",
"py32_usart1_clock_literal"
],
"extra-files": [
"src/device/py32/py32f001xx.s"
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f002axx"
],
"build-tags": [
"py32f002ax5"
],
"linkerscript": "targets/py32f002ax5.ld",
"flash-command": "pyocd load -t py32f002ax5 {bin}"
}
+9
View File
@@ -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"
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f002axx"
],
"extra-files": [
"src/device/py32/py32f002axx.s"
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f002bxx"
],
"build-tags": [
"py32f002bx5"
],
"linkerscript": "targets/py32f002bx5.ld",
"flash-command": "pyocd load -t py32f002bx5 {bin}"
}
+9
View File
@@ -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"
+12
View File
@@ -0,0 +1,12 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f002bxx",
"py32_no_gpio_afrh"
],
"extra-files": [
"src/device/py32/py32f002bxx.s"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002cxx"
],
"build-tags": [
"py32f002cx5"
],
"linkerscript": "targets/py32f002cx5.ld"
}
+9
View File
@@ -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"
+12
View File
@@ -0,0 +1,12 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f002cxx",
"py32_no_gpio_afrh"
],
"extra-files": [
"src/device/py32/py32f002cxx.s"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002xxx"
],
"build-tags": [
"py32f002xx2"
],
"linkerscript": "targets/py32f002xx2.ld"
}
+9
View File
@@ -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"
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002xxx"
],
"build-tags": [
"py32f002xx4"
],
"linkerscript": "targets/py32f002xx4.ld"
}
+9
View File
@@ -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"
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002xxx"
],
"build-tags": [
"py32f002xx5"
],
"linkerscript": "targets/py32f002xx5.ld"
}
+9
View File
@@ -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"
+12
View File
@@ -0,0 +1,12 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f002xxx",
"py32_no_gpio_afrh"
],
"extra-files": [
"src/device/py32/py32f002xxx.s"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f002zxx"
],
"build-tags": [
"py32f002zx4"
],
"linkerscript": "targets/py32f002zx4.ld"
}
+9
View File
@@ -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"
+12
View File
@@ -0,0 +1,12 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f002zxx",
"py32_no_gpio_afrh"
],
"extra-files": [
"src/device/py32/py32f002zxx.s"
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f003xx"
],
"build-tags": [
"py32f003x4"
],
"linkerscript": "targets/py32f003x4.ld",
"flash-command": "pyocd load -t py32f003x4 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f003xx"
],
"build-tags": [
"py32f003x6"
],
"linkerscript": "targets/py32f003x6.ld",
"flash-command": "pyocd load -t py32f003x6 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f003xx"
],
"build-tags": [
"py32f003x7"
],
"linkerscript": "targets/py32f003x7.ld",
"flash-command": "pyocd load -t py32f003x7 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f003xx"
],
"build-tags": [
"py32f003x8"
],
"linkerscript": "targets/py32f003x8.ld",
"flash-command": "pyocd load -t py32f003x8 {bin}"
}
+9
View File
@@ -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"
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f003xx"
],
"extra-files": [
"src/device/py32/py32f003xx.s"
]
}
+9
View File
@@ -0,0 +1,9 @@
{
"inherits": [
"py32f021xx"
],
"build-tags": [
"py32f021x8"
],
"linkerscript": "targets/py32f021x8.ld"
}
+9
View File
@@ -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"
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f021xx"
],
"extra-files": [
"src/device/py32/py32f021xx.s"
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f030xx"
],
"build-tags": [
"py32f030x4"
],
"linkerscript": "targets/py32f030x4.ld",
"flash-command": "pyocd load -t py32f030x4 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f030xx"
],
"build-tags": [
"py32f030x6"
],
"linkerscript": "targets/py32f030x6.ld",
"flash-command": "pyocd load -t py32f030x6 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f030xx"
],
"build-tags": [
"py32f030x7"
],
"linkerscript": "targets/py32f030x7.ld",
"flash-command": "pyocd load -t py32f030x7 {bin}"
}
+9
View File
@@ -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"
+10
View File
@@ -0,0 +1,10 @@
{
"inherits": [
"py32f030xx"
],
"build-tags": [
"py32f030x8"
],
"linkerscript": "targets/py32f030x8.ld",
"flash-command": "pyocd load -t py32f030x8 {bin}"
}
+9
View File
@@ -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"
+11
View File
@@ -0,0 +1,11 @@
{
"inherits": [
"py32"
],
"build-tags": [
"py32f030xx"
],
"extra-files": [
"src/device/py32/py32f030xx.s"
]
}
+9
View File
@@ -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