mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
targets: correct pin mapping for Arduino UNO Q STM32 MCU
Signed-off-by: deadprogram <ron@hybridgroup.com> machine/stm32u585: fix PWR peripheral clock was never enabled On STM32U5, PWR is on AHB3 and requires RCC.AHB3ENR.PWREN - unlike some other STM32 families where PWR is always clocked. Without this, all writes to PWR registers (including IO2SV for VDDIO2) were silently dropped, so GPIOG pins could never drive. Signed-off-by: deadprogram <ron@hybridgroup.com> target: correct I2C pin mapping for Arduino UNO Q Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
@@ -7,54 +7,64 @@ package machine
|
||||
import (
|
||||
"device/stm32"
|
||||
"runtime/interrupt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Arduino Pins
|
||||
A0 = PA0
|
||||
A1 = PA1
|
||||
A2 = PA4
|
||||
A3 = PB1
|
||||
A4 = PB11
|
||||
A5 = PB12
|
||||
A0 = PA4
|
||||
A1 = PA5
|
||||
A2 = PA6
|
||||
A3 = PA7
|
||||
A4 = PC1
|
||||
A5 = PC0
|
||||
|
||||
D0 = PB7
|
||||
D1 = PB6
|
||||
D2 = PA10
|
||||
D3 = PB3
|
||||
D4 = PB5
|
||||
D5 = PB4
|
||||
D6 = PB10
|
||||
D7 = PA8
|
||||
D8 = PA9
|
||||
D9 = PC7
|
||||
D10 = PB0
|
||||
D11 = PA7
|
||||
D12 = PA6
|
||||
D13 = PA5
|
||||
D14 = PB9
|
||||
D15 = PB8
|
||||
D2 = PB3
|
||||
D3 = PB0
|
||||
D4 = PA12
|
||||
D5 = PA11
|
||||
D6 = PB1
|
||||
D7 = PB2
|
||||
D8 = PB4
|
||||
D9 = PB8
|
||||
D10 = PB9
|
||||
D11 = PB15
|
||||
D12 = PB14
|
||||
D13 = PB13
|
||||
D18 = PC1
|
||||
D19 = PC0
|
||||
D20 = PB10
|
||||
D21 = PB11
|
||||
)
|
||||
|
||||
const (
|
||||
LED = LED_BUILTIN
|
||||
LED_BUILTIN = LED_GREEN
|
||||
LED_GREEN = PA5
|
||||
LED = LED3_R
|
||||
LED3_R = PH10
|
||||
LED3_G = PH11
|
||||
LED3_B = PH12
|
||||
LED4_R = PH13
|
||||
LED4_G = PH14
|
||||
LED4_B = PH15
|
||||
)
|
||||
|
||||
const (
|
||||
BUTTON = PC13
|
||||
)
|
||||
// Default UART pins (LPUART1 active via ST-LINK virtual COM port)
|
||||
UART_TX_PIN = PG7
|
||||
UART_RX_PIN = PG8
|
||||
|
||||
const (
|
||||
// UART pins
|
||||
// PA2 and PA3 are connected to the ST-Link Virtual Com Port (VCP)
|
||||
UART_TX_PIN = PA2
|
||||
UART_RX_PIN = PA3
|
||||
// USART1 pins (Arduino header D1/D0)
|
||||
UART1_TX_PIN = D1
|
||||
UART1_RX_PIN = D0
|
||||
|
||||
// LPUART1 pins (active via ST-LINK virtual COM port)
|
||||
UART2_TX_PIN = PG7
|
||||
UART2_RX_PIN = PG8
|
||||
|
||||
// I2C pins
|
||||
I2C0_SCL_PIN = PB8
|
||||
I2C0_SDA_PIN = PB9
|
||||
I2C0_SCL_PIN = D20
|
||||
I2C0_SDA_PIN = D21
|
||||
|
||||
// SPI pins
|
||||
SPI1_SCK_PIN = PA5
|
||||
@@ -66,23 +76,31 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// USART2 is the hardware serial port connected to the onboard ST-LINK
|
||||
// debugger to be exposed as virtual COM port over USB.
|
||||
// USART1 on PB6/PB7 (Arduino header D1/D0).
|
||||
UART1 = &_UART1
|
||||
_UART1 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: stm32.USART2,
|
||||
Bus: stm32.USART1,
|
||||
TxAltFuncSelector: AF7_USART1_2_3,
|
||||
RxAltFuncSelector: AF7_USART1_2_3,
|
||||
}
|
||||
DefaultUART = UART1
|
||||
|
||||
// I2C1 is documented, alias to I2C0 as well
|
||||
I2C1 = &I2C{
|
||||
Bus: stm32.I2C1,
|
||||
// LPUART1 on PG7/PG8 (active via ST-LINK virtual COM port).
|
||||
UART2 = &_UART2
|
||||
_UART2 = UART{
|
||||
Buffer: NewRingBuffer(),
|
||||
Bus: (*stm32.USART_Type)(unsafe.Pointer(stm32.LPUART1)),
|
||||
TxAltFuncSelector: AF8_UART4_5_LPUART1_SDMMC1,
|
||||
RxAltFuncSelector: AF8_UART4_5_LPUART1_SDMMC1,
|
||||
}
|
||||
DefaultUART = UART2
|
||||
|
||||
// I2C2 is documented, alias to I2C0 as well
|
||||
I2C2 = &I2C{
|
||||
Bus: stm32.I2C2,
|
||||
AltFuncSelector: AF4_I2C1_2_3_4,
|
||||
}
|
||||
I2C0 = I2C1
|
||||
I2C0 = I2C2
|
||||
|
||||
// SPI1 is documented, alias to SPI0 as well
|
||||
SPI1 = &SPI{
|
||||
@@ -93,5 +111,6 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
UART1.Interrupt = interrupt.New(stm32.IRQ_USART2, _UART1.handleInterrupt)
|
||||
UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)
|
||||
UART2.Interrupt = interrupt.New(stm32.IRQ_LPUART1, _UART2.handleInterrupt)
|
||||
}
|
||||
|
||||
@@ -236,13 +236,16 @@ func (p Pin) enableClock() {
|
||||
default:
|
||||
panic("machine: unknown port")
|
||||
}
|
||||
// Dummy read-back to ensure the clock enable takes effect before
|
||||
// accessing GPIO registers (2 AHB cycle delay per STM32 reference manual).
|
||||
_ = stm32.RCC.AHB2ENR1.Get()
|
||||
}
|
||||
|
||||
// Enable peripheral clock
|
||||
func enableAltFuncClock(bus unsafe.Pointer) {
|
||||
switch bus {
|
||||
case unsafe.Pointer(stm32.PWR): // Power interface clock enable
|
||||
// PWR clock is always enabled on U5 (no dedicated enable bit needed)
|
||||
stm32.RCC.AHB3ENR.SetBits(stm32.RCC_AHB3ENR_PWREN)
|
||||
case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable
|
||||
stm32.RCC.APB1ENR1.SetBits(stm32.RCC_APB1ENR1_I2C1EN)
|
||||
case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable
|
||||
|
||||
@@ -4,6 +4,7 @@ package machine
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
@@ -20,8 +21,23 @@ const APB2_TIM_FREQ = 4e6 // 4MHz (MSI default)
|
||||
|
||||
// Configure the UART.
|
||||
func (uart *UART) configurePins(config UARTConfig) {
|
||||
if uart.isLPUART1() {
|
||||
// LPUART1 is on APB3. Explicitly enable its peripheral clock.
|
||||
stm32.RCC.APB3ENR.SetBits(stm32.RCC_APB3ENR_LPUART1EN)
|
||||
_ = stm32.RCC.APB3ENR.Get() // delay for clock stabilization
|
||||
|
||||
// Select PCLK3 as LPUART1 kernel clock source.
|
||||
stm32.RCC.CCIPR3.ReplaceBits(
|
||||
stm32.RCC_CCIPR3_LPUART1SEL_PCLK3<<stm32.RCC_CCIPR3_LPUART1SEL_Pos,
|
||||
stm32.RCC_CCIPR3_LPUART1SEL_Msk, 0)
|
||||
}
|
||||
|
||||
if config.RX.getPort() == stm32.GPIOG || config.TX.getPort() == stm32.GPIOG {
|
||||
// Enable VDDIO2 power supply for PGx pins
|
||||
// Enable VDDIO2 voltage monitoring and wait for ready before
|
||||
// declaring VDDIO2 supply valid (matches HAL_PWREx_EnableVddIO2).
|
||||
stm32.PWR.SetSVMCR_IO2VMEN(1)
|
||||
for stm32.PWR.GetSVMSR_VDDIO2RDY() == 0 {
|
||||
}
|
||||
stm32.PWR.SetSVMCR_IO2SV(1)
|
||||
}
|
||||
|
||||
@@ -30,9 +46,18 @@ func (uart *UART) configurePins(config UARTConfig) {
|
||||
config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.RxAltFuncSelector)
|
||||
}
|
||||
|
||||
// isLPUART1 returns true if this UART is backed by the LPUART1 peripheral.
|
||||
func (uart *UART) isLPUART1() bool {
|
||||
return uintptr(unsafe.Pointer(uart.Bus)) == uintptr(unsafe.Pointer(stm32.LPUART1))
|
||||
}
|
||||
|
||||
// UART baudrate calc based on the bus and clockspeed
|
||||
// NOTE: keep this in sync with the runtime/runtime_stm32u5.go clock init code
|
||||
func (uart *UART) getBaudRateDivisor(baudRate uint32) uint32 {
|
||||
if uart.isLPUART1() {
|
||||
// LPUART uses BRR = 256 * fclk / baud
|
||||
return (256 * CPUFrequency()) / baudRate
|
||||
}
|
||||
return CPUFrequency() / baudRate
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"device/stm32"
|
||||
"machine"
|
||||
)
|
||||
|
||||
@@ -24,8 +25,9 @@ func buffered() int {
|
||||
|
||||
func initCLK() {
|
||||
// Use MSI at 4MHz — the reset default clock configuration.
|
||||
// This matches the known-working bare-metal C configuration for
|
||||
// the Arduino Uno Q (STM32U585). The MCU boots with MSI at 4MHz,
|
||||
// VOS Range 4, and 0 flash wait states. No additional configuration
|
||||
// is needed.
|
||||
// The MCU boots with MSI at 4MHz, VOS Range 4, and 0 flash wait states.
|
||||
|
||||
// Enable PWR peripheral clock (required on STM32U5 before accessing PWR registers).
|
||||
stm32.RCC.AHB3ENR.SetBits(stm32.RCC_AHB3ENR_PWREN)
|
||||
_ = stm32.RCC.AHB3ENR.Get() // read-back for clock stabilization
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user