From 62d4a6a77f6e7a35346277166a1ace143ab33ad0 Mon Sep 17 00:00:00 2001 From: Kenneth Bell Date: Thu, 11 Nov 2021 10:56:05 +0000 Subject: [PATCH] stm32: add minimal stm32wlex5 / lorae5 target credit to ofauchon --- Makefile | 2 + README.md | 1 + lib/stm32-svd | 2 +- src/machine/board_lorae5.go | 54 +++ src/machine/i2c.go | 3 +- src/machine/machine_stm32_exti_syscfg.go | 3 +- .../machine_stm32_exti_syscfg_noenable.go | 27 ++ src/machine/machine_stm32_gpio_reva.go | 3 +- src/machine/machine_stm32_gpio_revb.go | 1 + src/machine/machine_stm32_gpio_revb_mp.go | 87 +++++ src/machine/machine_stm32_spi.go | 3 +- src/machine/machine_stm32wle5.go | 343 ++++++++++++++++++ src/machine/spi.go | 3 +- src/runtime/runtime_stm32wle5.go | 26 ++ targets/lorae5.json | 12 + targets/stm32wle5.json | 8 + targets/stm32wle5.ld | 10 + 17 files changed, 582 insertions(+), 6 deletions(-) create mode 100644 src/machine/board_lorae5.go create mode 100644 src/machine/machine_stm32_exti_syscfg_noenable.go create mode 100644 src/machine/machine_stm32_gpio_revb_mp.go create mode 100644 src/machine/machine_stm32wle5.go create mode 100644 src/runtime/runtime_stm32wle5.go create mode 100644 targets/lorae5.json create mode 100644 targets/stm32wle5.json create mode 100644 targets/stm32wle5.ld diff --git a/Makefile b/Makefile index b57eaaff..d4a1e82a 100644 --- a/Makefile +++ b/Makefile @@ -430,6 +430,8 @@ ifneq ($(STM32), 0) @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=stm32f4disco-1 examples/pwm @$(MD5SUM) test.hex + $(TINYGO) build -size short -o test.hex -target=lorae5 examples/blinky1 + @$(MD5SUM) test.hex endif ifneq ($(AVR), 0) $(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial diff --git a/README.md b/README.md index 53d4f47b..2252f6fd 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ The following 72 microcontroller boards are currently supported: * [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199) * [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) * [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html) +* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html) * [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html) * [SiFIve HiFive1](https://www.sifive.com/boards/hifive1) * [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html) diff --git a/lib/stm32-svd b/lib/stm32-svd index 3a0b0829..5f417214 160000 --- a/lib/stm32-svd +++ b/lib/stm32-svd @@ -1 +1 @@ -Subproject commit 3a0b0829b70bf930c74fb69d887bee28005e7d99 +Subproject commit 5f417214efe79598eadd38f68b4432384ca57456 diff --git a/src/machine/board_lorae5.go b/src/machine/board_lorae5.go new file mode 100644 index 00000000..d6634b4a --- /dev/null +++ b/src/machine/board_lorae5.go @@ -0,0 +1,54 @@ +//go:build lorae5 +// +build lorae5 + +package machine + +import ( + "device/stm32" + "runtime/interrupt" +) + +const ( + LED1 = PB5 + LED = LED1 // Default LED +) + +// SubGhz (SPI3) +const ( + SPI0_NSS_PIN = PA4 + SPI0_SCK_PIN = PA5 + SPI0_SDO_PIN = PA6 + SPI0_SDI_PIN = PA7 +) + +// UARTS +const ( + //MCU USART1 + UART1_TX_PIN = PB6 + UART1_RX_PIN = PB7 + + //MCU USART2 + UART2_TX_PIN = PA2 + UART2_RX_PIN = PA3 + + // DEFAULT USART + UART_TX_PIN = UART1_TX_PIN + UART_RX_PIN = UART1_RX_PIN +) + +var ( + // Console UART + UART0 = &_UART0 + _UART0 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART1, + TxAltFuncSelector: AF7_USART1_2, + RxAltFuncSelector: AF7_USART1_2, + } + DefaultUART = UART0 +) + +func init() { + // Enable UARTs Interrupts + UART0.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART0.handleInterrupt) +} diff --git a/src/machine/i2c.go b/src/machine/i2c.go index 5e66c36e..737e7a4c 100644 --- a/src/machine/i2c.go +++ b/src/machine/i2c.go @@ -1,4 +1,5 @@ -// +build atmega nrf sam stm32 fe310 k210 rp2040 +//go:build atmega || nrf || sam || (stm32 && !stm32wle5) || fe310 || k210 || rp2040 +// +build atmega nrf sam stm32,!stm32wle5 fe310 k210 rp2040 package machine diff --git a/src/machine/machine_stm32_exti_syscfg.go b/src/machine/machine_stm32_exti_syscfg.go index 34d111fb..3b3680ae 100644 --- a/src/machine/machine_stm32_exti_syscfg.go +++ b/src/machine/machine_stm32_exti_syscfg.go @@ -1,4 +1,5 @@ -// +build stm32,!stm32f1,!stm32l5 +//go:build stm32 && !stm32f1 && !stm32l5 && !stm32wle5 +// +build stm32,!stm32f1,!stm32l5,!stm32wle5 package machine diff --git a/src/machine/machine_stm32_exti_syscfg_noenable.go b/src/machine/machine_stm32_exti_syscfg_noenable.go new file mode 100644 index 00000000..576d77ae --- /dev/null +++ b/src/machine/machine_stm32_exti_syscfg_noenable.go @@ -0,0 +1,27 @@ +//go:build stm32wle5 +// +build stm32wle5 + +package machine + +import ( + "device/stm32" + "runtime/volatile" +) + +func getEXTIConfigRegister(pin uint8) *volatile.Register32 { + switch (pin & 0xf) / 4 { + case 0: + return &stm32.SYSCFG.EXTICR1 + case 1: + return &stm32.SYSCFG.EXTICR2 + case 2: + return &stm32.SYSCFG.EXTICR3 + case 3: + return &stm32.SYSCFG.EXTICR4 + } + return nil +} + +func enableEXTIConfigRegisters() { + // No registers to enable +} diff --git a/src/machine/machine_stm32_gpio_reva.go b/src/machine/machine_stm32_gpio_reva.go index 3c0d4fe0..19b68386 100644 --- a/src/machine/machine_stm32_gpio_reva.go +++ b/src/machine/machine_stm32_gpio_reva.go @@ -1,4 +1,5 @@ -// +build stm32,!stm32l4,!stm32l5 +//go:build stm32 && !stm32l4 && !stm32l5 && !stm32wle5 +// +build stm32,!stm32l4,!stm32l5,!stm32wle5 package machine diff --git a/src/machine/machine_stm32_gpio_revb.go b/src/machine/machine_stm32_gpio_revb.go index 1a0e3537..7329f47e 100644 --- a/src/machine/machine_stm32_gpio_revb.go +++ b/src/machine/machine_stm32_gpio_revb.go @@ -1,3 +1,4 @@ +//go:build stm32l4 || stm32l5 // +build stm32l4 stm32l5 package machine diff --git a/src/machine/machine_stm32_gpio_revb_mp.go b/src/machine/machine_stm32_gpio_revb_mp.go new file mode 100644 index 00000000..a8d058fb --- /dev/null +++ b/src/machine/machine_stm32_gpio_revb_mp.go @@ -0,0 +1,87 @@ +//go:build stm32wle5 +// +build stm32wle5 + +package machine + +import ( + "device/stm32" +) + +// +// This variant of the GPIO input interrupt logic is for +// multi-core chips with a larger number of interrupt +// channels (more than fits in a single register). +// +// This logic is currently used by the single-core stm32wle5 +// due to a patch in stm32-rs project that has renamed the +// registers to match the dual-core names. This renaming is +// being discussed and may change in future. +// + +// +// STM32 allows one interrupt source per pin number, with +// the same pin number in different ports sharing a single +// interrupt source (so PA0, PB0, PC0 all share). Only a +// single physical pin can be connected to each interrupt +// line. +// +// To call interrupt callbacks, we record here for each +// pin number the callback and the actual associated pin. +// + +// Callbacks for pin interrupt events +var pinCallbacks [16]func(Pin) + +// The pin currently associated with interrupt callback +// for a given slot. +var interruptPins [16]Pin + +// SetInterrupt sets an interrupt to be executed when a particular pin changes +// state. The pin should already be configured as an input, including a pull up +// or down if no external pull is provided. +// +// This call will replace a previously set callback on this pin. You can pass a +// nil func to unset the pin change interrupt. If you do so, the change +// parameter is ignored and can be set to any value (such as 0). +func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error { + port := uint32(uint8(p) / 16) + pin := uint8(p) % 16 + + enableEXTIConfigRegisters() + + if callback == nil { + stm32.EXTI.C1IMR1.ClearBits(1 << pin) + pinCallbacks[pin] = nil + return nil + } + + if pinCallbacks[pin] != nil { + // The pin was already configured. + // To properly re-configure a pin, unset it first and set a new + // configuration. + return ErrNoPinChangeChannel + } + + // Set the callback now (before the interrupt is enabled) to avoid + // possible race condition + pinCallbacks[pin] = callback + interruptPins[pin] = p + + crReg := getEXTIConfigRegister(pin) + shift := (pin & 0x3) * 4 + crReg.ReplaceBits(port, 0xf, shift) + + if (change & PinRising) != 0 { + stm32.EXTI.RTSR1.SetBits(1 << pin) + } + if (change & PinFalling) != 0 { + stm32.EXTI.FTSR1.SetBits(1 << pin) + } + stm32.EXTI.C1IMR1.SetBits(1 << pin) + + intr := p.registerInterrupt() + intr.SetPriority(0) + intr.Enable() + + return nil +} diff --git a/src/machine/machine_stm32_spi.go b/src/machine/machine_stm32_spi.go index 62623492..f9179a2f 100644 --- a/src/machine/machine_stm32_spi.go +++ b/src/machine/machine_stm32_spi.go @@ -1,4 +1,5 @@ -// +build stm32,!stm32f7x2,!stm32l5x2 +//go:build stm32 && !stm32f7x2 && !stm32l5x2 && !stm32wle5 +// +build stm32,!stm32f7x2,!stm32l5x2,!stm32wle5 package machine diff --git a/src/machine/machine_stm32wle5.go b/src/machine/machine_stm32wle5.go new file mode 100644 index 00000000..cd9653df --- /dev/null +++ b/src/machine/machine_stm32wle5.go @@ -0,0 +1,343 @@ +//go:build stm32wle5 +// +build stm32wle5 + +package machine + +// Peripheral abstraction layer for the stm32wle5 + +import ( + "device/stm32" + "runtime/interrupt" + "runtime/volatile" + "unsafe" +) + +const ( + AF0_SYSTEM = 0 + AF1_TIM1_2_LPTIM1 = 1 + AF2_TIM1_2 = 2 + AF3_SPIS2_TIM1_LPTIM3 = 3 + AF4_I2C1_2_3 = 4 + AF5_SPI1_SPI2S2 = 5 + AF6_RF = 6 + AF7_USART1_2 = 7 + AF8_LPUART1 = 8 + AF12_COMP1_2_TIM1 = 12 + AF13_DEBUG = 13 + AF14_TIM2_16_17_LPTIM2 = 14 + AF15_EVENTOUT = 15 +) + +func CPUFrequency() uint32 { + return 4e6 +} + +const APB1_TIM_FREQ = 4e6 +const APB2_TIM_FREQ = 4e6 + +const ( + PA0 = portA + 0 + PA1 = portA + 1 + PA2 = portA + 2 + PA3 = portA + 3 + PA4 = portA + 4 + PA5 = portA + 5 + PA6 = portA + 6 + PA7 = portA + 7 + PA8 = portA + 8 + PA9 = portA + 9 + PA10 = portA + 10 + PA11 = portA + 11 + PA12 = portA + 12 + PA13 = portA + 13 + PA14 = portA + 14 + PA15 = portA + 15 + + PB0 = portB + 0 + PB1 = portB + 1 + PB2 = portB + 2 + PB3 = portB + 3 + PB4 = portB + 4 + PB5 = portB + 5 + PB6 = portB + 6 + PB7 = portB + 7 + PB8 = portB + 8 + PB9 = portB + 9 + PB10 = portB + 10 + PB11 = portB + 11 + PB12 = portB + 12 + PB13 = portB + 13 + PB14 = portB + 14 + PB15 = portB + 15 + + PC0 = portC + 0 + PC1 = portC + 1 + PC2 = portC + 2 + PC3 = portC + 3 + PC4 = portC + 4 + PC5 = portC + 5 + PC6 = portC + 6 + PC7 = portC + 7 + PC8 = portC + 8 + PC9 = portC + 9 + PC10 = portC + 10 + PC11 = portC + 11 + PC12 = portC + 12 + PC13 = portC + 13 + PC14 = portC + 14 + PC15 = portC + 15 + + PH3 = portH + 3 +) + +func (p Pin) getPort() *stm32.GPIO_Type { + switch p / 16 { + case 0: + return stm32.GPIOA + case 1: + return stm32.GPIOB + case 2: + return stm32.GPIOC + case 7: + return stm32.GPIOH + default: + panic("machine: unknown port") + } +} + +// enableClock enables the clock for this desired GPIO port. +func (p Pin) enableClock() { + switch p / 16 { + case 0: + stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOAEN) + case 1: + stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOBEN) + case 2: + stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOCEN) + case 7: + stm32.RCC.AHB2ENR.SetBits(stm32.RCC_AHB2ENR_GPIOHEN) + default: + panic("machine: unknown port") + } +} + +// Enable peripheral clock +func enableAltFuncClock(bus unsafe.Pointer) { + switch bus { + // APB1ENR1 + case unsafe.Pointer(stm32.LPTIM1): // LPTIM1 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_LPTIM1EN) + case unsafe.Pointer(stm32.DAC): // DAC clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_DAC1EN) + case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C3EN) + case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C2EN) + case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN) + case unsafe.Pointer(stm32.USART2): // USART2 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_USART2EN) + case unsafe.Pointer(stm32.SPI2): // SPI2S2 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_SPI2S2EN) + case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_WWDGEN) + case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable + stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_TIM2EN) + // APB1ENR2 + case unsafe.Pointer(stm32.LPTIM3): // LPTIM3 clock enable + stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM3EN) + case unsafe.Pointer(stm32.LPTIM2): // LPTIM2 clock enable + stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPTIM2EN) + case unsafe.Pointer(stm32.LPUART): // LPUART clock enable + stm32.RCC.APB1ENR2.SetBits(stm32.RCC_APB1ENR2_LPUART1EN) + //APB2ENR + case unsafe.Pointer(stm32.TIM17): // TIM17 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM17EN) + case unsafe.Pointer(stm32.TIM16): // TIM16 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM16EN) + case unsafe.Pointer(stm32.USART1): // USART1 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) + case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN) + case unsafe.Pointer(stm32.TIM1): // TIM1 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_TIM1EN) + case unsafe.Pointer(stm32.ADC): // ADC clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN) + + } +} + +func handlePinInterrupt(pin uint8) { + if stm32.EXTI.PR1.HasBits(1 << pin) { + // Writing 1 to the pending register clears the + // pending flag for that bit + stm32.EXTI.PR1.Set(1 << pin) + + callback := pinCallbacks[pin] + if callback != nil { + callback(interruptPins[pin]) + } + } +} + +func (p Pin) registerInterrupt() interrupt.Interrupt { + pin := uint8(p) % 16 + + switch pin { + case 0: + return interrupt.New(stm32.IRQ_EXTI0, func(interrupt.Interrupt) { handlePinInterrupt(0) }) + case 1: + return interrupt.New(stm32.IRQ_EXTI1, func(interrupt.Interrupt) { handlePinInterrupt(1) }) + case 2: + return interrupt.New(stm32.IRQ_EXTI2, func(interrupt.Interrupt) { handlePinInterrupt(2) }) + case 3: + return interrupt.New(stm32.IRQ_EXTI3, func(interrupt.Interrupt) { handlePinInterrupt(3) }) + case 4: + return interrupt.New(stm32.IRQ_EXTI4, func(interrupt.Interrupt) { handlePinInterrupt(4) }) + case 5: + return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(5) }) + case 6: + return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(6) }) + case 7: + return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(7) }) + case 8: + return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(8) }) + case 9: + return interrupt.New(stm32.IRQ_EXTI9_5, func(interrupt.Interrupt) { handlePinInterrupt(9) }) + case 10: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(10) }) + case 11: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(11) }) + case 12: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(12) }) + case 13: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(13) }) + case 14: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(14) }) + case 15: + return interrupt.New(stm32.IRQ_EXTI15_10, func(interrupt.Interrupt) { handlePinInterrupt(15) }) + } + + return interrupt.Interrupt{} +} + +//---------- UART related code + +// Configure the UART. +func (uart UART) configurePins(config UARTConfig) { + // enable the alternate functions on the TX and RX pins + config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.TxAltFuncSelector) + config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector) +} + +// UART baudrate calc based on the bus and clockspeed +// NOTE: keep this in sync with the runtime/runtime_stm32wle5.go clock init code +func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 { + var br uint32 + uartClock := CPUFrequency() // No Prescaler configuration + br = uint32((uartClock + baudRate/2) / baudRate) + return (br) +} + +// Register names vary by ST processor, these are for STM L5 +func (uart *UART) setRegisters() { + uart.rxReg = &uart.Bus.RDR + uart.txReg = &uart.Bus.TDR + uart.statusReg = &uart.Bus.ISR + uart.txEmptyFlag = stm32.USART_ISR_TXFNF //(TXFNF == TXE == bit 7, but depends alternate RM0461/1094) +} + +//---------- Timer related code + +var ( + TIM1 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM1EN, + Device: stm32.TIM1, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{{PA8, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA9, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA10, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA11, AF1_TIM1_2_LPTIM1}}}, + }, + busFreq: APB2_TIM_FREQ, + } + TIM2 = TIM{ + EnableRegister: &stm32.RCC.APB1ENR1, + EnableFlag: stm32.RCC_APB1ENR1_TIM2EN, + Device: stm32.TIM2, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{{PA0, AF1_TIM1_2_LPTIM1}, {PA5, AF1_TIM1_2_LPTIM1}, {PA15, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA1, AF1_TIM1_2_LPTIM1}, {PB3, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA2, AF1_TIM1_2_LPTIM1}, {PB10, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{{PA3, AF1_TIM1_2_LPTIM1}, {PB11, AF1_TIM1_2_LPTIM1}}}, + }, + busFreq: APB1_TIM_FREQ, + } + TIM16 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM16EN, + Device: stm32.TIM16, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{{PA6, AF14_TIM2_16_17_LPTIM2}}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } + TIM17 = TIM{ + EnableRegister: &stm32.RCC.APB2ENR, + EnableFlag: stm32.RCC_APB2ENR_TIM17EN, + Device: stm32.TIM17, + Channels: [4]TimerChannel{ + TimerChannel{Pins: []PinFunction{{PA7, AF1_TIM1_2_LPTIM1}, {PB9, AF1_TIM1_2_LPTIM1}}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + TimerChannel{Pins: []PinFunction{}}, + }, + busFreq: APB2_TIM_FREQ, + } +) + +func (t *TIM) registerUPInterrupt() interrupt.Interrupt { + switch t { + case &TIM1: + return interrupt.New(stm32.IRQ_TIM1_UP, TIM1.handleUPInterrupt) + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleUPInterrupt) + case &TIM16: + return interrupt.New(stm32.IRQ_TIM16, TIM16.handleUPInterrupt) + case &TIM17: + return interrupt.New(stm32.IRQ_TIM17, TIM17.handleUPInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) registerOCInterrupt() interrupt.Interrupt { + switch t { + case &TIM1: + return interrupt.New(stm32.IRQ_TIM1_CC, TIM1.handleOCInterrupt) + case &TIM2: + return interrupt.New(stm32.IRQ_TIM2, TIM2.handleOCInterrupt) + case &TIM16: + return interrupt.New(stm32.IRQ_TIM16, TIM16.handleOCInterrupt) + case &TIM17: + return interrupt.New(stm32.IRQ_TIM17, TIM17.handleOCInterrupt) + } + + return interrupt.Interrupt{} +} + +func (t *TIM) enableMainOutput() { + t.Device.BDTR.SetBits(stm32.TIM_BDTR_MOE) +} + +type arrtype = uint32 +type arrRegType = volatile.Register32 + +const ( + ARR_MAX = 0x10000 + PSC_MAX = 0x10000 +) diff --git a/src/machine/spi.go b/src/machine/spi.go index 80f7c133..398c5c16 100644 --- a/src/machine/spi.go +++ b/src/machine/spi.go @@ -1,4 +1,5 @@ -// +build !baremetal stm32,!stm32f7x2,!stm32l5x2 fe310 k210 atmega +//go:build !baremetal || (stm32 && !stm32f7x2 && !stm32l5x2 && !stm32wle5) || fe310 || k210 || atmega +// +build !baremetal stm32,!stm32f7x2,!stm32l5x2,!stm32wle5 fe310 k210 atmega package machine diff --git a/src/runtime/runtime_stm32wle5.go b/src/runtime/runtime_stm32wle5.go new file mode 100644 index 00000000..598faff8 --- /dev/null +++ b/src/runtime/runtime_stm32wle5.go @@ -0,0 +1,26 @@ +//go:build stm32wle5 +// +build stm32wle5 + +package runtime + +import ( + "machine" +) + +type arrtype = uint32 + +func init() { + // Currently the clock is not configured, which means + // the MCU runs at default reset clock speed (4Mhz). + // Code to initialize RCC and PLL can go here. + + // UART init + machine.Serial.Configure(machine.UARTConfig{}) + + // Timers init + initTickTimer(&machine.TIM1) +} + +func putchar(c byte) { + machine.Serial.WriteByte(c) +} diff --git a/targets/lorae5.json b/targets/lorae5.json new file mode 100644 index 00000000..9b33125c --- /dev/null +++ b/targets/lorae5.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "stm32wle5" + ], + "build-tags": [ + "lorae5" + ], + "serial": "uart", + "flash-method": "openocd", + "openocd-interface": "stlink-v2", + "openocd-target": "stm32wlx" +} \ No newline at end of file diff --git a/targets/stm32wle5.json b/targets/stm32wle5.json new file mode 100644 index 00000000..ac3b8bce --- /dev/null +++ b/targets/stm32wle5.json @@ -0,0 +1,8 @@ +{ + "inherits": ["cortex-m4"], + "build-tags": ["stm32wle5", "stm32"], + "extra-files": [ + "src/device/stm32/stm32wle5.s" + ], + "linkerscript": "targets/stm32wle5.ld" +} \ No newline at end of file diff --git a/targets/stm32wle5.ld b/targets/stm32wle5.ld new file mode 100644 index 00000000..59b61690 --- /dev/null +++ b/targets/stm32wle5.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 256K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} + +_stack_size = 4K; + +INCLUDE "targets/arm.ld" \ No newline at end of file