diff --git a/.gitignore b/.gitignore index 2761d1fcc7..0b03c83ead 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ src/device/renesas/*.go src/device/renesas/*.s src/device/rp/*.go src/device/rp/*.s +src/device/py32/*.go +src/device/py32/*.s ./vendor llvm-build llvm-project diff --git a/.gitmodules b/.gitmodules index 1f8c63a673..b09cf7fb2e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,3 +41,6 @@ [submodule "lib/bdwgc"] path = lib/bdwgc url = https://github.com/ivmai/bdwgc.git +[submodule "lib/py32-svd"] + path = lib/py32-svd + url = https://github.com/burgrp/py32-svd.git diff --git a/GNUmakefile b/GNUmakefile index 99dc3913b6..69689a0a33 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -187,7 +187,7 @@ fmt-check: ## Warn if any source needs reformatting @unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1 -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 @@ -242,6 +242,10 @@ 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 + $(LLVM_PROJECTDIR)/llvm: git clone -b xtensa_release_19.1.2 --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR) llvm-source: $(LLVM_PROJECTDIR)/llvm ## Get LLVM sources diff --git a/lib/py32-svd b/lib/py32-svd new file mode 160000 index 0000000000..d98c758f53 --- /dev/null +++ b/lib/py32-svd @@ -0,0 +1 @@ +Subproject commit d98c758f530cfa61e607334b50e19f6c113f8d1d diff --git a/src/machine/board_embedfire_py32f002b.go b/src/machine/board_embedfire_py32f002b.go new file mode 100644 index 0000000000..ab5ef80a6f --- /dev/null +++ b/src/machine/board_embedfire_py32f002b.go @@ -0,0 +1,27 @@ +//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 +) + +// UART +const ( + DEFAULT_UART_TX_PIN = PA6 + DEFAULT_UART_RX_PIN = PA7 + DEFAULT_UART_TX_PIN_AF = 1 + DEFAULT_UART_RX_PIN_AF = 3 +) diff --git a/src/machine/board_embedfire_py32f030.go b/src/machine/board_embedfire_py32f030.go new file mode 100644 index 0000000000..7d32dab314 --- /dev/null +++ b/src/machine/board_embedfire_py32f030.go @@ -0,0 +1,27 @@ +//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 +) + +// UART +const ( + DEFAULT_UART_TX_PIN = PA7 + DEFAULT_UART_RX_PIN = PA8 + DEFAULT_UART_TX_PIN_AF = 8 + DEFAULT_UART_RX_PIN_AF = 8 +) diff --git a/src/machine/machine_py32_pin.go b/src/machine/machine_py32_pin.go new file mode 100644 index 0000000000..d244439408 --- /dev/null +++ b/src/machine/machine_py32_pin.go @@ -0,0 +1,220 @@ +//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 + PinInputFloating + PinInputPulldown + PinInputPullup + PinInputAnalog +) +const PinInput PinMode = PinInputFloating + +const ( + gpioModeInput = 0 + gpioModeOutput = 1 + gpioModeAnalog = 3 + gpioModeMask = 0x3 + + gpioPullFloating = 0 + gpioPullUp = 1 + gpioPullDown = 2 + gpioPullMask = 0x3 + + gpioOutputSpeedHigh = 2 + gpioOutputSpeedMask = 0x3 +) + +func (p Pin) getPortNumber() uint8 { + return uint8(p) >> 4 + +} + +func (p Pin) getPinNumber() uint8 { + return uint8(p) & 0x0F +} + +func (p Pin) getPort() (*py32.GPIO_Type, uint8) { + offset := uintptr(p.getPortNumber()) * (uintptr(unsafe.Pointer(py32.GPIOB)) - uintptr(unsafe.Pointer(py32.GPIOA))) + return (*py32.GPIO_Type)(unsafe.Pointer(uintptr(unsafe.Pointer(py32.GPIOA)) + offset)), p.getPinNumber() +} + +func (p Pin) Set(high bool) { + port, pin := p.getPort() + if high { + port.BSRR.Set(1 << pin) + } else { + port.BSRR.Set(1 << (pin + 16)) + } +} + +func (p Pin) Get() bool { + port, pin := p.getPort() + val := port.IDR.Get() & (1 << pin) + return val > 0 +} + +func (p Pin) Configure(config PinConfig) { + p.enableClock() + port, pin := p.getPort() + pos := (pin % 16) * 2 + + switch config.Mode { + + case PinInputFloating: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + case PinInputPulldown: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos) + case PinInputPullup: + port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) + case PinOutput: + port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos) + port.OTYPER.ReplaceBits(py32.GPIO_OTYPER_OT0_PushPull, py32.GPIO_OTYPER_OT0_Msk, pos>>1) + port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + case PinInputAnalog: + port.MODER.ReplaceBits(gpioModeAnalog, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos) + } +} + +func (p Pin) enableClock() { + portNo := p.getPortNumber() + py32.RCC.IOPENR.SetBits(1 << portNo) +} diff --git a/src/machine/machine_py32_pin_afrh.go b/src/machine/machine_py32_pin_afrh.go new file mode 100644 index 0000000000..7077bd4de8 --- /dev/null +++ b/src/machine/machine_py32_pin_afrh.go @@ -0,0 +1,12 @@ +//go:build py32 && !no_gpio_afrh + +package machine + +func (p Pin) SetAltFunc(af uint8) { + port, pin := p.getPort() + if pin >= 8 { + port.AFRH.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } else { + port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) + } +} diff --git a/src/machine/machine_py32_pin_no_afrh.go b/src/machine/machine_py32_pin_no_afrh.go new file mode 100644 index 0000000000..fb674db8f4 --- /dev/null +++ b/src/machine/machine_py32_pin_no_afrh.go @@ -0,0 +1,8 @@ +//go:build py32 && no_gpio_afrh + +package machine + +func (p Pin) SetAltFunc(af uint8) { + port, pin := p.getPort() + port.AFRL.ReplaceBits(uint32(af), 0xF, (pin%8)*4) +} diff --git a/src/machine/machine_py32_uart.go b/src/machine/machine_py32_uart.go new file mode 100644 index 0000000000..8cbe6fc27c --- /dev/null +++ b/src/machine/machine_py32_uart.go @@ -0,0 +1,104 @@ +//go:build py32 + +package machine + +import ( + "device/py32" + "runtime/interrupt" +) + +// Remember the clock used for baud rate calculations so Configure() can be +// called without explicitly passing the clock. +var py32UARTClockHz uint32 = 24_000_000 + +// UART implements a minimal USART1 driver for PY32 parts. +type UART struct { + Bus *py32.USART_Type + Buffer *RingBuffer + irq interrupt.Interrupt +} + +var DefaultUART = &UART{Bus: py32.USART1, Buffer: NewRingBuffer()} + +// ConfigureWithClock initializes the UART using the provided peripheral clock +// frequency (in Hz). This avoids assuming a fixed MCU clock. +func (uart *UART) ConfigureWithClock(config UARTConfig, clockHz uint32) error { + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + // Configure default pins if they weren't provided. + if config.TX == 0 { + ConfigureUARTPin(DEFAULT_UART_TX_PIN, DEFAULT_UART_TX_PIN_AF) + } + + if config.RX == 0 { + ConfigureUARTPin(DEFAULT_UART_RX_PIN, DEFAULT_UART_RX_PIN_AF) + } + + // Enable peripheral clock. + py32.RCC.APBENR2.SetBits(py32.RCC_APBENR2_USART1EN) + + // Reset control registers to a known state. + uart.Bus.CR1.Set(0) + uart.Bus.CR2.Set(0) + uart.Bus.CR3.Set(0) + + // Oversampling by 16: BRR expects fck/baud. + divider := (clockHz + (config.BaudRate / 2)) / config.BaudRate + uart.Bus.BRR.Set(divider) + + // Enable transmitter, receiver, RX interrupt, and the peripheral. + uart.Bus.CR1.Set(py32.USART_CR1_TE | py32.USART_CR1_RE | py32.USART_CR1_RXNEIE | py32.USART_CR1_UE) + + // Hook interrupt. + uart.irq = interrupt.New(py32.IRQ_USART1, handleUartInterrupt) + uart.irq.SetPriority(0xc0) + uart.irq.Enable() + + return nil +} + +// Configure uses the last stored clock (defaulting to 24 MHz). Call +// ConfigureWithClock for explicit control. +func (uart *UART) Configure(config UARTConfig) error { + return uart.ConfigureWithClock(config, py32UARTClockHz) +} + +// InitSerialWithClock configures the default Serial using the supplied +// peripheral clock frequency. +func InitSerialWithClock(clockHz uint32) { + py32UARTClockHz = clockHz + //Serial.ConfigureWithClock(UARTConfig{}, clockHz) +} + +// Configure pin for use by UART +func ConfigureUARTPin(pin Pin, af uint8) { + pin.enableClock() + port, n := pin.getPort() + pos := (n % 16) * 2 + + // Alternate function mode is encoded as 0b10. + port.MODER.ReplaceBits(2, gpioModeMask, pos) + port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos) + port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos) + pin.SetAltFunc(af) +} + +func handleUartInterrupt(interrupt.Interrupt) { + uart := DefaultUART + data := uint8(uart.Bus.DR.Get()) + uart.Receive(data) +} + +func (uart *UART) writeByte(c byte) error { + for uart.Bus.SR.Get()&py32.USART_SR_TXE == 0 { + } + uart.Bus.DR.Set(uint32(c)) + return nil +} + +func (uart *UART) flush() { + for uart.Bus.SR.Get()&py32.USART_SR_TC == 0 { + } +} diff --git a/src/machine/uart.go b/src/machine/uart.go index 32462587b1..e154672e0c 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -1,4 +1,4 @@ -//go:build atmega || esp || nrf || sam || sifive || stm32 || k210 || nxp || rp2040 || rp2350 +//go:build atmega || esp || nrf || sam || sifive || stm32 || k210 || nxp || rp2040 || rp2350 || py32 package machine diff --git a/src/runtime/runtime_cortexm_hardfault.go b/src/runtime/runtime_cortexm_hardfault.go index b2449ed910..c5d2444e59 100644 --- a/src/runtime/runtime_cortexm_hardfault.go +++ b/src/runtime/runtime_cortexm_hardfault.go @@ -1,4 +1,4 @@ -//go:build atsamd21 || nrf51 +//go:build atsamd21 || nrf51 || py32 package runtime diff --git a/src/runtime/runtime_cortexm_hardfault_debug.go b/src/runtime/runtime_cortexm_hardfault_debug.go index ea6c507028..f54a4d6cae 100644 --- a/src/runtime/runtime_cortexm_hardfault_debug.go +++ b/src/runtime/runtime_cortexm_hardfault_debug.go @@ -1,4 +1,4 @@ -//go:build cortexm && !atsamd21 && !nrf51 +//go:build cortexm && !atsamd21 && !nrf51 && !py32 package runtime diff --git a/src/runtime/runtime_py32.go b/src/runtime/runtime_py32.go new file mode 100644 index 0000000000..4088d49b62 --- /dev/null +++ b/src/runtime/runtime_py32.go @@ -0,0 +1,78 @@ +//go:build py32 + +package runtime + +import ( + "device/arm" + "machine" + + "device/py32" + + "runtime/volatile" +) + +var tickCounter volatile.Register64 + +//export Reset_Handler +func main() { + preinit() + + py32.RCC.SetICSCR_HSI_FS(py32.RCC_ICSCR_HSI_FS_Freq24MHz) + + ConfigureSystemTimer(24_000_000) + machine.InitSerial() + + run() + exit(0) +} + +// Configure SysTick to fire every 1ms on given system frequency. +// This should be called after any changes to the system clock frequency. +func ConfigureSystemTimer(systemFrequencyHz uint32) { + arm.SetupSystemTimer(systemFrequencyHz / 1000) +} + +func ticksToNanoseconds(ticks timeUnit) int64 { + return int64(ticks * 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) +} diff --git a/targets/embedfire-py32f002b.json b/targets/embedfire-py32f002b.json new file mode 100644 index 0000000000..b3d339bc79 --- /dev/null +++ b/targets/embedfire-py32f002b.json @@ -0,0 +1,74 @@ +{ + "inherits": ["py32f002b"], + "flash-command": "pyocd load -t py32f002bx5 {bin}", + "build-tags": ["embedfire_py32f002b"] +} + +/* + +https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f002b" + +# dimensions counted in pins +width: 8 +height: 11 + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://img.sanishtech.com/u/8f427259002707501b471ef06a77134c.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + back: + src: "https://img.sanishtech.com/u/3650f247f0b77ef5efbcfca3d75f29aa.png" + top: -450 + left: -90 + right: -90 + bottom: -450 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "5V:power" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "KEY2:button", "PA0:gpio" ] + - [ "LED2:led", "PA1:gpio" ] + - [ "SWCLK:prog", "PA2:gpio" ] + - [ "KEY1:button", "PA3:gpio" ] + - [ "LED4:led", "PA4:gpio"] + - [ "RESET:button", "PC0:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "PB5:gpio" ] + - [ "PB4:gpio" ] + - [ "PB3:gpio" ] + - [ "SWDIO:prog", "PB6:gpio" ] + - [ "PB7:gpio" ] + - [ "PC1:gpio" ] + - [ "LED3:led", "PA5:gpio" ] + - [ "PA7:gpio"] + - [ "PA6:gpio"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' + + +*/ \ No newline at end of file diff --git a/targets/embedfire-py32f030.json b/targets/embedfire-py32f030.json new file mode 100644 index 0000000000..b198c38c95 --- /dev/null +++ b/targets/embedfire-py32f030.json @@ -0,0 +1,86 @@ +{ + "inherits": ["py32f030_64k_8k"], + "flash-command": "pyocd load -t py32f003x8 {bin}", + "build-tags": ["embedfire_py32f030"] +} + +/* + +https://splitbrain.github.io/pinoutleaf + +title: "embedfire-py32f030" + +# dimensions counted in pins +width: 8 +height: 16 + +# images can be URLs, use adjustments to fit the pins +image: + front: + src: "https://img.sanishtech.com/u/d7efa5b8e309a987d89bf3f031a4b5e3.png" + top: -520 + left: -120 + right: -120 + bottom: -470 + back: + src: "https://img.sanishtech.com/u/cfc8cd0828646e3bde5c1364fca33458.png" + top: -450 + left: -100 + right: -120 + bottom: -470 + +# Define the pins (label:type), use empty entries when offsets are needed +pins: + left: + - [ "3V3:power" ] + - [ "PA12:gpio" ] + - [ "SWDIO:prog", "PA13:gpio" ] + - [ "SWCLK:prog", "PA14:gpio" ] + - [ "PA11:gpio" ] + - [ "PA15:gpio" ] + - [ "PB3:gpio" ] + - [ "PB4:gpio" ] + - [ "PB5:gpio"] + - [ "PB6:gpio"] + - [ "PB7:gpio"] + - [ "BOOT0:config", "PF4:gpio"] + - [ "PB8:gpio"] + - [ "PF3:gpio"] + - [ "RESET:button", "PF2:gpio"] + - [ "GND:gnd"] + right: + - [ "3V3:power" ] + - [ "5V:power" ] + - [ "PA8:gpio" ] + - [ "PB2:gpio" ] + - [ "PB1:gpio" ] + - [ "PB0:gpio" ] + - [ "PA7:gpio" ] + - [ "KEY2:button", "PA6:gpio" ] + - [ "KEY1:button", "PA5:gpio"] + - [ "LED4:led", "PA4:gpio"] + - [ "LED3:led", "PA3:gpio"] + - [ "LED2:led", "PA2:gpio"] + - [ "PA1:gpio"] + - [ "PA0:gpio"] + - [ "GND:gnd"] + - [ "GND:gnd"] + +types: + gpio: + label: 'GPIO' + bgcolor: '#00A060' + prog: + label: 'SWD' + bgcolor: '#FFCC00' + led: + label: 'LED' + bgcolor: '#0099FF' + button: + label: 'Button' + bgcolor: '#B0B0B0' + config: + label: 'Config' + bgcolor: '#A060FF' + +*/ \ No newline at end of file diff --git a/targets/py32.json b/targets/py32.json new file mode 100644 index 0000000000..6424ef633a --- /dev/null +++ b/targets/py32.json @@ -0,0 +1,10 @@ +{ + "inherits": [ + "cortex-m0plus" + ], + "scheduler": "none", + "gc": "none", + "build-tags": [ + "py32" + ] +} \ No newline at end of file diff --git a/targets/py32f002b.json b/targets/py32f002b.json new file mode 100644 index 0000000000..2c0c82d8bc --- /dev/null +++ b/targets/py32f002b.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f002bxx", "no_gpio_afrh" + ], + "linkerscript": "targets/py32f002b.ld", + "extra-files": [ + "src/device/py32/py32f002axx.s" + ] +} \ No newline at end of file diff --git a/targets/py32f002b.ld b/targets/py32f002b.ld new file mode 100644 index 0000000000..3ed1dc12d0 --- /dev/null +++ b/targets/py32f002b.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 20K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 3K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" \ No newline at end of file diff --git a/targets/py32f030.json b/targets/py32f030.json new file mode 100644 index 0000000000..e1bc19bed0 --- /dev/null +++ b/targets/py32f030.json @@ -0,0 +1,11 @@ +{ + "inherits": [ + "py32" + ], + "build-tags": [ + "py32f030", "py32f030xx" + ], + "extra-files": [ + "src/device/py32/py32f030xx.s" + ] +} \ No newline at end of file diff --git a/targets/py32f030_64k_8k.json b/targets/py32f030_64k_8k.json new file mode 100644 index 0000000000..6a248733d8 --- /dev/null +++ b/targets/py32f030_64k_8k.json @@ -0,0 +1,9 @@ +{ + "inherits": [ + "py32f030" + ], + "build-tags": [ + "py32f030_64k_8k" + ], + "linkerscript": "targets/py32f030_64k_8k.ld" +} \ No newline at end of file diff --git a/targets/py32f030_64k_8k.ld b/targets/py32f030_64k_8k.ld new file mode 100644 index 0000000000..380a4d3811 --- /dev/null +++ b/targets/py32f030_64k_8k.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K +} + +_stack_size = 512; + +INCLUDE "targets/arm.ld" \ No newline at end of file