Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/examples/pwm/nucleo-h743zi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build stm32h743

package main

import "machine"

var (
pwm = &machine.TIM1
pinA = machine.PA8
pinB = machine.PA9
)
31 changes: 31 additions & 0 deletions src/examples/wwdg/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"machine"
"time"
)

func main() {
time.Sleep(2 * time.Second)

println("configuring window watchdog")
config := machine.WindowWatchdogConfig{
TimeoutMicros: 100000, // 100ms
WindowPercent: 50, // 50ms to 100ms refresh window
}

machine.WindowWatchdog.Configure(config)
machine.WindowWatchdog.Start()

println("updating wwdg for 1 second")
for i := 0; i < 10; i++ {
time.Sleep(75 * time.Millisecond) // middle of the window
machine.WindowWatchdog.Update()
println("alive")
}

println("entering tight loop (will reset)")
for {
time.Sleep(10 * time.Millisecond)
}
}
102 changes: 102 additions & 0 deletions src/machine/board_nucleoh753zi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//go:build nucleoh753zi

package machine

import (
"device/stm32"
"runtime/interrupt"
)

const (
// Arduino Pins
A0 = PA3
A1 = PC0
A2 = PC3
A3 = PB1
A4 = PC2
A5 = PF10

D0 = PG9
D1 = PG14
D2 = PF15
D3 = PE13
D4 = PF14
D5 = PE11
D6 = PE9
D7 = PF13
D8 = PF12
D9 = PD15
D10 = PD14
D11 = PA7
D12 = PA6
D13 = PA5
D14 = PB9
D15 = PB8
)

const (
LED = LED_BUILTIN
LED_BUILTIN = LED_GREEN
LED_GREEN = PB0
LED_YELLOW = PE1
LED_RED = PB14
)

const (
BUTTON = BUTTON_USER
BUTTON_USER = PC13
)

// UART pins
const (
// PD8 and PD9 are connected to the ST-Link Virtual Com Port (VCP)
UART_TX_PIN = PD8
UART_RX_PIN = PD9
UART_ALT_FN = AF7_SPI2_3_USART1_2_3_UART5_SPDIFRX
)

var (
// USART3 is the hardware serial port connected to the onboard ST-LINK
// debugger to be exposed as virtual COM port over USB on Nucleo boards.
UART1 = &_UART1
_UART1 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART3,
TxAltFuncSelector: UART_ALT_FN,
RxAltFuncSelector: UART_ALT_FN,
}
DefaultUART = UART1
)

func init() {
UART1.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART1.handleInterrupt)
}

// SPI pins
const (
SPI0_SCK_PIN = PA5
SPI0_SDI_PIN = PA6
SPI0_SDO_PIN = PA7
)

var (
SPI1 = &SPI{
Bus: stm32.SPI1,
AltFuncSelector: AF5_SPI1_2_3_4_5_6_I2S,
}
SPI0 = SPI1
)

// I2C pins
const (
I2C0_SCL_PIN = PB8
I2C0_SDA_PIN = PB9
)

var (
I2C1 = &I2C{
Bus: stm32.I2C1,
AltFuncSelector: AF4_I2C1_2_3_4_USART1,
}
I2C0 = I2C1
)
182 changes: 182 additions & 0 deletions src/machine/machine_stm32_adc_h7.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
//go:build stm32h7

package machine

import (
"device/stm32"
)

// InitADC initializes the registers needed for ADC1 and ADC3.
func InitADC() {
// 1. Enable ADC bus clocks
stm32.RCC.AHB1ENR.SetBits(stm32.RCC_AHB1ENR_ADC12EN)
stm32.RCC.AHB4ENR.SetBits(stm32.RCC_AHB4ENR_ADC3EN)

// 2. Configure ADC clock mode (Async from kernel clock)
// CCR is at offset 0x308 from ADC base.
stm32.ADC12_Common.CR.ReplaceBits(0x0, 0x3, 16) // CKMODE = 00
stm32.ADC3_Common.CR.ReplaceBits(0x0, 0x3, 16) // CKMODE = 00

// 3. Exit deep power-down mode
stm32.ADC1.CR.ClearBits(stm32.ADC_CR_DEEPPWD)
stm32.ADC3.CR.ClearBits(stm32.ADC_CR_DEEPPWD)

// 4. Enable voltage regulators
stm32.ADC1.CR.SetBits(stm32.ADC_CR_ADVREGEN)
stm32.ADC3.CR.SetBits(stm32.ADC_CR_ADVREGEN)
// Wait for T_ADCVREG_STUP (min 10us).
for i := 0; i < 10000; i++ {
// Busy wait
}

// Set BOOST[1:0]=0b11 for ADC kernel clock >25MHz (RM0433 §25.4.3 Table 121).
// The kernel clock is 80MHz (PLL2_P), so BOOST must be enabled.
stm32.ADC1.CR.ReplaceBits(0b11, 0x3, stm32.ADC_CR_BOOST_Pos)
stm32.ADC3.CR.ReplaceBits(0b11, 0x3, stm32.ADC_CR_BOOST_Pos)

// 5. Calibration
// ADC1
stm32.ADC1.CR.SetBits(stm32.ADC_CR_ADCAL | stm32.ADC_CR_ADCALLIN)
for stm32.ADC1.CR.HasBits(stm32.ADC_CR_ADCAL) {
}
// ADC3
stm32.ADC3.CR.SetBits(stm32.ADC_CR_ADCAL | stm32.ADC_CR_ADCALLIN)
for stm32.ADC3.CR.HasBits(stm32.ADC_CR_ADCAL) {
}

// 6. Enable ADCs
// ADC1
stm32.ADC1.ISR.SetBits(stm32.ADC_ISR_ADRDY) // Clear ADRDY by writing 1
stm32.ADC1.CR.SetBits(stm32.ADC_CR_ADEN)
for !stm32.ADC1.ISR.HasBits(stm32.ADC_ISR_ADRDY) {
}
// ADC3
stm32.ADC3.ISR.SetBits(stm32.ADC_ISR_ADRDY) // Clear ADRDY by writing 1
stm32.ADC3.CR.SetBits(stm32.ADC_CR_ADEN)
for !stm32.ADC3.ISR.HasBits(stm32.ADC_ISR_ADRDY) {
}

// 7. Configure resolution (16-bit)
// RES[2:0] is at bits 4:2 in CFGR. 000: 16-bit.
stm32.ADC1.CFGR.ReplaceBits(0x0, 0x7, 2)
stm32.ADC3.CFGR.ReplaceBits(0x0, 0x7, 2)
}

// Configure configures an ADC pin to be able to read analog data.
func (a ADC) Configure(config ADCConfig) {
a.Pin.Configure(PinConfig{Mode: PinInputAnalog})

// Set sampling time.
// H7 has SMPR1 (channels 0-9) and SMPR2 (channels 10-19).
// Each channel has 3 bits.
ch := a.getChannel()
adc, _ := a.getPeripheral()
const smpVal = 0x2 // 8.5 cycles
if ch <= 9 {
adc.SMPR1.ReplaceBits(uint32(smpVal), 0x7, uint8(ch)*3)
} else {
adc.SMPR2.ReplaceBits(uint32(smpVal), 0x7, uint8(ch-10)*3)
}
}

// Get returns the current value of an ADC pin in the range 0..0xffff.
func (a ADC) Get() uint16 {
ch := uint32(a.getChannel())
adc, ok := a.getPeripheral()
if !ok {
return 0
}

// Select channel (PCSEL register)
// Refer to RM0433 §25.4.12: Only one PCSELx bit must be set at a time.
adc.PCSEL.Set(1 << ch)

// Set rank 1 to channel
// SQ1[4:0] at bits 10:6. L[3:0] at bits 3:0.
adc.SQR1.ReplaceBits(ch, 0x1F, 6)
adc.SQR1.ReplaceBits(0x0, 0xF, 0) // L=0 (1 conversion)

// Start conversion
adc.CR.SetBits(stm32.ADC_CR_ADSTART)

// Wait for end of conversion
for !adc.ISR.HasBits(stm32.ADC_ISR_EOC) {
}

// Read 16-bit result
result := uint16(adc.DR.Get())

// Clear EOC
adc.ISR.SetBits(stm32.ADC_ISR_EOC)

// Deselect channel
adc.PCSEL.Set(0)

return result
}

func (a ADC) getPeripheral() (*stm32.ADC_Type, bool) {
switch a.Pin {
case PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10:
return stm32.ADC3, true
default:
// Assume ADC1 for PA/PB/PC pins
return stm32.ADC1, true
}
}

// getChannel returns the ADC channel number for a given GPIO pin.
// Mapping for STM32H743 per RM0433 and DS12110.
func (a ADC) getChannel() uint8 {
switch a.Pin {
case PA0:
return 16
case PA1:
return 17
case PA2:
return 14
case PA3:
return 15
case PA4:
return 18
case PA5:
return 19
case PA6:
return 3
case PA7:
return 7
case PB0:
return 9
case PB1:
return 5
case PC0:
return 10
case PC1:
return 11
case PC2:
return 12
case PC3:
return 13
case PC4:
return 4
case PC5:
return 8
case PF3:
return 5
case PF4:
return 9
case PF5:
return 4
case PF6:
return 8
case PF7:
return 3
case PF8:
return 7
case PF9:
return 2
case PF10:
return 6
}
return 0
}
2 changes: 1 addition & 1 deletion src/machine/machine_stm32_exti_syscfg.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build stm32 && !stm32f1 && !stm32l5 && !stm32wlx && !stm32g0 && !stm32u5
//go:build stm32 && !stm32f1 && !stm32l5 && !stm32wlx && !stm32g0 && !stm32u5 && !stm32h7

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/machine/machine_stm32_gpio_reva.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build stm32 && !stm32l4 && !stm32l5 && !stm32wlx && !stm32g0 && !stm32u5
//go:build stm32 && !stm32l4 && !stm32l5 && !stm32wlx && !stm32g0 && !stm32u5 && !stm32h7

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/machine/machine_stm32_i2c_revb.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build stm32l5 || stm32f7 || stm32l4 || stm32l0 || stm32wlx || stm32g0 || stm32u5
//go:build stm32l5 || stm32f7 || stm32l4 || stm32l0 || stm32wlx || stm32g0 || stm32u5 || stm32h7

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/machine/machine_stm32_spi.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build stm32 && !stm32f7x2 && !stm32l5x2 && !stm32g0 && !stm32u5
//go:build stm32 && !stm32f7x2 && !stm32l5x2 && !stm32g0 && !stm32u5 && !stm32h7

package machine

Expand Down
19 changes: 19 additions & 0 deletions src/machine/machine_stm32_tim.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ func (t *TIM) Count() uint32 {
return uint32(t.Device.CNT.Get())
}

// SetOnePulseMode enables or disables the one-pulse mode.
// When enabled, the timer will automatically stop at the next update event.
func (t *TIM) SetOnePulseMode(enable bool) {
if enable {
t.Device.CR1.SetBits(stm32.TIM_CR1_OPM)
} else {
t.Device.CR1.ClearBits(stm32.TIM_CR1_OPM)
}
}

// SetEnabled enables or disables the timer.
func (t *TIM) SetEnabled(enable bool) {
if enable {
t.Device.CR1.SetBits(stm32.TIM_CR1_CEN)
} else {
t.Device.CR1.ClearBits(stm32.TIM_CR1_CEN)
}
}

// SetWraparoundInterrupt configures a callback to be called each
// time the timer 'wraps-around'.
//
Expand Down
Loading